Skip to content

Commit

Permalink
Merge b6205fc into 0aacc7e
Browse files Browse the repository at this point in the history
  • Loading branch information
rachealerhard committed Feb 25, 2022
2 parents 0aacc7e + b6205fc commit 7ba9a95
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 80 deletions.
22 changes: 11 additions & 11 deletions regression/scripts/slipstream/slipstream_test.py
Expand Up @@ -117,14 +117,14 @@ def regress_1b(results, configs):
sectional_lift_coeff = results.segments.cruise.conditions.aerodynamics.lift_breakdown.inviscid_wings_sectional[0]

# lift coefficient and sectional lift coefficient check
lift_coefficient_true = 0.43754861958748476
sectional_lift_coeff_true = np.array([ 4.40811415e-01, 3.58447605e-01, 3.53758756e-01, 3.05402561e-01,
5.87270843e-02, 4.49276571e-01, 3.95135393e-01, 3.67274586e-01,
3.11407447e-01, 5.99032728e-02, -6.60176707e-02, -6.27939836e-02,
-5.54634997e-02, -4.12681130e-02, -2.43572153e-02, -7.26029863e-02,
-7.03806008e-02, -6.17510582e-02, -4.64116740e-02, -2.76739451e-02,
3.50749550e-07, 1.99325526e-09, 1.55733197e-09, 4.01202494e-09,
2.44844282e-09])
lift_coefficient_true = 0.43754882067868917
sectional_lift_coeff_true = np.array([ 4.40783762e-01, 3.58418575e-01, 3.53731767e-01, 3.05377941e-01,
5.87221701e-02, 4.49249435e-01, 3.95108681e-01, 3.67248534e-01,
3.11383278e-01, 5.98984462e-02, -6.58338027e-02, -6.26213370e-02,
-5.53134063e-02, -4.11543791e-02, -2.42887824e-02, -7.24163411e-02,
-7.02015156e-02, -6.15927770e-02, -4.62903773e-02, -2.76006287e-02,
3.50583837e-07, 1.98446900e-09, 1.57066352e-09, 4.03406286e-09,
2.45046493e-09])

diff_CL = np.abs(lift_coefficient - lift_coefficient_true)
print('CL difference')
Expand Down Expand Up @@ -208,9 +208,9 @@ def Lift_Rotor_Slipstream(wake_fidelity):

def regress_2(results):

CL_truth = 0.41609632
CDi_truth = 0.00826812
CM_truth = 0.3235729
CL_truth = 0.41618253
CDi_truth = 0.00703032
CM_truth = 0.32351636

CL = results.CL
CDi = results.CDi
Expand Down
63 changes: 58 additions & 5 deletions trunk/SUAVE/Analyses/Propulsion/Rotor_Wake_Fidelity_One.py
Expand Up @@ -8,14 +8,17 @@
# Imports
# ----------------------------------------------------------------------
from SUAVE.Core import Data
from SUAVE.Components import Wings
from SUAVE.Components.Energy.Energy_Component import Energy_Component
from SUAVE.Analyses.Propulsion.Rotor_Wake_Fidelity_Zero import Rotor_Wake_Fidelity_Zero
from SUAVE.Methods.Propulsion.Rotor_Wake.Fidelity_One.fidelity_one_wake_convergence import fidelity_one_wake_convergence
from SUAVE.Methods.Propulsion.Rotor_Wake.Fidelity_One.compute_wake_induced_velocity import compute_wake_induced_velocity

from SUAVE.Methods.Aerodynamics.Common.Fidelity_Zero.Lift.extract_wing_VD import extract_wing_collocation_points

# package imports
import copy

import numpy as np
# ----------------------------------------------------------------------
# Generalized Rotor Class
# ----------------------------------------------------------------------
Expand Down Expand Up @@ -153,7 +156,60 @@ def evaluate(self,rotor,wake_inputs,conditions):

return va, vt

def evaluate_wake_velocities(self,rotor,network,geometry,conditions,VD,num_ctrl_pts):
def evaluate_slipstream(self,rotor,geometry,ctrl_pts,wing_instance=None):
"""
Evaluates the velocities induced by the rotor on a specified wing of the vehicle.
If no wing instance is specified, uses main wing or last available wing in geometry.
Assumptions:
None
Source:
N/A
Inputs:
self - rotor wake
rotor - rotor
geometry - vehicle geometry
Outputs:
wake_V_ind - induced velocity from rotor wake at (VD.XC, VD.YC, VD.ZC)
Properties Used:
None
"""
# Check for wing if wing instance is unspecified
if wing_instance == None:
nmw = 0
# check for main wing
for i,wing in enumerate(geometry.wings):
if not isinstance(wing,Wings.Main_Wing): continue
nmw +=1
wing_instance = wing
wing_instance_idx = i
if nmw == 1:
pass
elif nmw>1:
print("No wing specified for slipstream analysis. Multiple main wings in vehicle, using the last one.")
else:
print("No wing specified for slipstream analysis. No main wing defined, using the last wing in vehicle.")
wing_instance = wing
wing_instance_idx = i

# Isolate the VD components corresponding to this wing instance
wing_CPs, slipstream_vd_ids = extract_wing_collocation_points(geometry, wing_instance_idx)

# Evaluate rotor slipstream effect on specified wing instance
rot_V_wake_ind = self.evaluate_wake_velocities(rotor, wing_CPs, ctrl_pts)

# Expand
wake_V_ind = np.zeros((ctrl_pts,geometry.vortex_distribution.n_cp,3))
wake_V_ind[:,slipstream_vd_ids,:] = rot_V_wake_ind


return wake_V_ind

def evaluate_wake_velocities(self,rotor,VD,num_ctrl_pts):
"""
Links the rotor wake to compute the wake-induced velocities at the vortex distribution
control points.
Expand All @@ -167,9 +223,6 @@ def evaluate_wake_velocities(self,rotor,network,geometry,conditions,VD,num_ctrl_
Inputs:
self - rotor wake
rotor - rotor
network - propulsion network
geometry - vehicle geometry
conditions - conditions
VD - vortex distribution
num_ctrl_pts - number of analysis control points
Expand Down
79 changes: 63 additions & 16 deletions trunk/SUAVE/Analyses/Propulsion/Rotor_Wake_Fidelity_Zero.py
Expand Up @@ -11,10 +11,13 @@
from SUAVE.Components.Energy.Energy_Component import Energy_Component


from SUAVE.Components import Wings
from SUAVE.Methods.Propulsion.Rotor_Wake.Fidelity_Zero.fidelity_zero_wake_convergence import fidelity_zero_wake_convergence
from SUAVE.Methods.Propulsion.Rotor_Wake.Fidelity_Zero.compute_bevw_induced_velocity import compute_bevw_induced_velocity
from SUAVE.Methods.Propulsion.Rotor_Wake.Fidelity_Zero.compute_fidelity_zero_induced_velocity import compute_fidelity_zero_induced_velocity

from SUAVE.Methods.Aerodynamics.Common.Fidelity_Zero.Lift.extract_wing_VD import extract_wing_collocation_points

import numpy as np
# ----------------------------------------------------------------------
# Generalized Rotor Class
# ----------------------------------------------------------------------
Expand Down Expand Up @@ -88,10 +91,10 @@ def evaluate(self,rotor,wake_inputs,conditions):

return va, vt

def evaluate_wake_velocities(self,rotor,network,geometry,conditions,VD,num_ctrl_pts):
def evaluate_slipstream(self,rotor,geometry,ctrl_pts,wing_instance=None):
"""
Links the rotor wake to compute the wake-induced velocities at the vortex distribution
control points.
Evaluates the velocities induced by the rotor on a specified wing of the vehicle.
If no wing instance is specified, uses main wing or last available wing in geometry.
Assumptions:
None
Expand All @@ -102,11 +105,60 @@ def evaluate_wake_velocities(self,rotor,network,geometry,conditions,VD,num_ctrl_
Inputs:
self - rotor wake
rotor - rotor
network - propulsion network
geometry - vehicle geometry
conditions - conditions
VD - vortex distribution
num_ctrl_pts - number of analysis control points
Outputs:
wake_V_ind - induced velocity from rotor wake at (VD.XC, VD.YC, VD.ZC)
Properties Used:
None
"""
# Check for wing if wing instance is unspecified
if wing_instance == None:
nmw = 0
# check for main wing
for i,wing in enumerate(geometry.wings):
if not isinstance(wing,Wings.Main_Wing): continue
nmw +=1
wing_instance = wing
wing_instance_idx = i
if nmw == 1:
pass
elif nmw>1:
print("No wing specified for slipstream analysis. Multiple main wings in vehicle, using the last one.")
else:
print("No wing specified for slipstream analysis. No main wing defined, using the last wing in vehicle.")
wing_instance = wing
wing_instance_idx = i

# Isolate the VD components corresponding to this wing instance
wing_CPs, slipstream_vd_ids = extract_wing_collocation_points(geometry, wing_instance_idx)

# Evaluate rotor slipstream effect on specified wing instance
rot_V_wake_ind = self.evaluate_wake_velocities(rotor, wing_CPs,ctrl_pts)

# Expand
wake_V_ind = np.zeros((ctrl_pts,geometry.vortex_distribution.n_cp,3))
wake_V_ind[:,slipstream_vd_ids,:] = rot_V_wake_ind


return wake_V_ind

def evaluate_wake_velocities(self,rotor,evaluation_points,ctrl_pts):
"""
Links the rotor wake to compute the wake-induced velocities at the specified
evaluation points.
Assumptions:
None
Source:
N/A
Inputs:
self - rotor wake
rotor - rotor
evaluation_points - points at which to evaluate the rotor wake-induced velocities
Outputs:
prop_V_wake_ind - induced velocity from rotor wake at (VD.XC, VD.YC, VD.ZC)
Expand All @@ -115,14 +167,9 @@ def evaluate_wake_velocities(self,rotor,network,geometry,conditions,VD,num_ctrl_
None
"""

identical_flag = network.identical_propellers

if network.number_of_propeller_engines == None:
pass
else:
rots = Data()
rots.append(rotor)
rot_V_wake_ind = compute_bevw_induced_velocity(rots,geometry,num_ctrl_pts,conditions,identical_flag)
rots = Data()
rots.append(rotor)
rot_V_wake_ind = compute_fidelity_zero_induced_velocity(evaluation_points,rots,ctrl_pts)

return rot_V_wake_ind

2 changes: 1 addition & 1 deletion trunk/SUAVE/Input_Output/VTK/save_prop_vtk.py
Expand Up @@ -339,7 +339,7 @@ def generate_lofted_propeller_points(prop):
a_o = prop.start_angle

n_r = len(b) # number radial points
n_a_loft = prop.number_points_around_airfoil # number points around airfoil
n_a_loft = prop.vtk_airfoil_points # number points around airfoil
theta = np.linspace(0,2*np.pi,num_B+1)[:-1] # azimuthal stations

# create empty data structure for storing propeller geometries
Expand Down
Expand Up @@ -94,7 +94,7 @@ def compute_RHS_matrix(delta,phi,conditions,settings,geometry,propeller_wake_mod
prop_V_wake_ind = np.zeros((num_ctrl_pts,num_eval_pts,3))

for p in props:
prop_V_wake_ind += p.Wake.evaluate_wake_velocities(p,network,geometry,conditions,VD,num_ctrl_pts)
prop_V_wake_ind += p.Wake.evaluate_slipstream(p,geometry,num_ctrl_pts)


if 'lift_rotors' in network.keys():
Expand All @@ -103,7 +103,7 @@ def compute_RHS_matrix(delta,phi,conditions,settings,geometry,propeller_wake_mod
rot_V_wake_ind = np.zeros((num_ctrl_pts,num_eval_pts,3))

for r in rots:
rot_V_wake_ind += r.Wake.evaluate_wake_velocities(r,network,geometry,conditions,VD,num_ctrl_pts)
rot_V_wake_ind += r.Wake.evaluate_slipstream(r,geometry,num_ctrl_pts)


# update the total induced velocity distribution
Expand Down
@@ -0,0 +1,67 @@
## @ingroup Methods-Aerodynamics-Common-Fidelity_Zero-Lift
# extract_wing_collocation_points.py
#
# Created: Feb 2022, R. Erhard
# Modified:

# ----------------------------------------------------------------------
# Imports
# ----------------------------------------------------------------------

# package imports
import numpy as np
from SUAVE.Core import Data

## @ingroup Methods-Aerodynamics-Common-Fidelity_Zero-Lift
def extract_wing_collocation_points(geometry, wing_instance_idx):

""" This extracts the collocation points of the vehicle vortex distribution
belonging to the specified wing instance index. This is used for
Source:
None
Inputs:
geometry - SUAVE vehicle
wing_instance - wing instance to extract VD for
Outputs:
None
Properties Used:
N/A
"""
# unpack vortex distribution properties
VD = geometry.vortex_distribution
n_sw = VD.n_sw
n_cw = VD.n_cw

VD_wing = Data()
vd_i = 0 # count of current VD wing elements
j = 0 # count of current VD wing index
size = n_cw * n_sw

for idx,wing in enumerate(geometry.wings):

if wing.symmetric:
wing_cp_size = size[j] + size[j+1]
j += 2
else:
wing_cp_size = size[j]
j += 1

if idx == wing_instance_idx:
# store the VD corresponding to this wing
VD_wing.XC = VD.XC[vd_i : vd_i + wing_cp_size]
VD_wing.YC = VD.YC[vd_i : vd_i + wing_cp_size]
VD_wing.ZC = VD.ZC[vd_i : vd_i + wing_cp_size]
VD_wing.n_cp = len(VD_wing.XC)

ids = (np.linspace(vd_i, vd_i+wing_cp_size-1, wing_cp_size)).astype(int)

vd_i += wing_cp_size


return VD_wing, ids


@@ -1,5 +1,5 @@
## @defgroup Methods-Aerodynamics-Rotor_Wake-Fidelity_Zero
# Rotor wake methods that are directly specified by analyses.

from .compute_bevw_induced_velocity import compute_bevw_induced_velocity
from .compute_wake_contraction_matrix import compute_wake_contraction_matrix
from .compute_fidelity_zero_induced_velocity import compute_fidelity_zero_induced_velocity
from .compute_wake_contraction_matrix import compute_wake_contraction_matrix

0 comments on commit 7ba9a95

Please sign in to comment.