Skip to content

Commit

Permalink
Merge 5972e37 into 7c6f1dc
Browse files Browse the repository at this point in the history
  • Loading branch information
rachealerhard committed Mar 2, 2022
2 parents 7c6f1dc + 5972e37 commit 43cd699
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 87 deletions.
23 changes: 12 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.4375681814886325
sectional_lift_coeff_true = np.array([ 4.39186743e-01, 3.55022830e-01, 3.51363002e-01, 3.03463863e-01,
5.83427225e-02, 4.49490617e-01, 4.03740726e-01, 3.68481887e-01,
3.11492900e-01, 6.01164743e-02, -6.61621250e-02, -6.28443495e-02,
-5.56118594e-02, -4.13996846e-02, -2.44318893e-02, -7.41588710e-02,
-7.19859998e-02, -6.32091207e-02, -4.77136327e-02, -2.85404276e-02,
5.13437911e-07, 2.71732702e-09, 2.85037078e-09, 6.96361700e-09,
4.19821840e-09])

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

def regress_2(results):

CL_truth = 0.41609632
CDi_truth = 0.00826812
CM_truth = 0.06915052
CL_truth = 0.41618253
CDi_truth = 0.00703032
CM_truth = 0.0690942


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

3 changes: 2 additions & 1 deletion trunk/SUAVE/Components/Energy/Converters/Rotor.py
Expand Up @@ -545,7 +545,8 @@ def spin(self,conditions):
blade_H_distribution = rotor_drag_distribution,
rotor_drag = rotor_drag,
rotor_drag_coefficient = Crd,
figure_of_merit = FoM
figure_of_merit = FoM,
tip_mach = omega * R / conditions.freestream.speed_of_sound
)
self.outputs = outputs

Expand Down
6 changes: 2 additions & 4 deletions trunk/SUAVE/Input_Output/VTK/save_prop_vtk.py
Expand Up @@ -323,7 +323,6 @@ def generate_lofted_propeller_points(prop):
beta = prop.twist_distribution
b = prop.chord_distribution
r = prop.radius_distribution
MCA = prop.mid_chord_alignment
t = prop.max_thickness_distribution
origin = prop.origin

Expand All @@ -339,7 +338,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 All @@ -350,7 +349,6 @@ def generate_lofted_propeller_points(prop):
flip_1 = (np.pi/2)
flip_2 = (np.pi/2)

MCA_2d = np.repeat(np.atleast_2d(MCA).T,n_a_loft,axis=1)
b_2d = np.repeat(np.atleast_2d(b).T ,n_a_loft,axis=1)
t_2d = np.repeat(np.atleast_2d(t).T ,n_a_loft,axis=1)
r_2d = np.repeat(np.atleast_2d(r).T ,n_a_loft,axis=1)
Expand Down Expand Up @@ -378,7 +376,7 @@ def generate_lofted_propeller_points(prop):
max_t2d = np.repeat(np.atleast_2d(max_t).T ,n_a_loft,axis=1)

airfoil_le_offset = ( - np.repeat(b[:,None], n_a_loft, axis=1)/2 ) # no sweep
xp = (- MCA_2d + xpts*b_2d + airfoil_le_offset) # x coord of airfoil
xp = (xpts*b_2d + airfoil_le_offset) # x coord of airfoil
yp = r_2d*np.ones_like(xp) # radial location
zp = zpts*(t_2d/max_t2d) # former airfoil y coord

Expand Down
2 changes: 1 addition & 1 deletion trunk/SUAVE/Input_Output/VTK/save_vehicle_vtk.py
Expand Up @@ -22,7 +22,7 @@
import numpy as np

## @ingroup Input_Output-VTK
def save_vehicle_vtks(vehicle, conditions=None, Results=None, time_step=0,VLM_settings=None, prop_filename="propeller.vtk", rot_filename="rotor.vtk",
def save_vehicle_vtks(vehicle, conditions=None, Results=Data(), time_step=0,VLM_settings=None, prop_filename="propeller.vtk", rot_filename="rotor.vtk",
wake_filename="prop_wake.vtk", wing_vlm_filename="wing_vlm_horseshoes.vtk",wing_filename="wing_vlm.vtk",
fuselage_filename="fuselage.vtk", nacelle_filename="nacelle.vtk", save_loc=None):
"""
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,54 @@
## @ingroup Methods-Aerodynamics-Common-Fidelity_Zero-Lift
# extract_wing_VD.py
#
# Created: Feb 2022, R. Erhard
# Modified:

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

# package imports
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 useful for slipstream
analysis, where the wake of a propeller is included in the VLM analysis
of a specified wing in the vehicle.
Source:
None
Inputs:
geometry - SUAVE vehicle
wing_instance - wing instance tag
Outputs:
VD_wing - colocation points of vortex distribution for specified wing
ids - indices in the vortex distribution corresponding to specified wing
Properties Used:
N/A
"""
# unpack vortex distribution properties
VD = geometry.vortex_distribution
span_breaks = VD.spanwise_breaks
wing = list(geometry.wings.keys())[wing_instance_idx]
sym = geometry.wings[wing].symmetric

VD_wing = Data()
id_start = span_breaks[wing_instance_idx]
id_end = span_breaks[wing_instance_idx + 1 + int(sym)]
ids = range(id_start,id_end)

VD_wing.XC = VD.XC[ids]
VD_wing.YC = VD.YC[ids]
VD_wing.ZC = VD.ZC[ids]
VD_wing.n_cp = len(VD_wing.XC)

return VD_wing, ids


Expand Up @@ -39,8 +39,8 @@ def import_airfoil_polars(airfoil_polar_files):
num_polars = 0
for i in range(num_airfoils):
n_p = len(airfoil_polar_files[i])
if n_p < 3:
raise AttributeError('Provide three or more airfoil polars to compute surrogate')
#if n_p < 3:
#raise AttributeError('Provide three or more airfoil polars to compute surrogate')

num_polars = max(num_polars, n_p)

Expand Down
@@ -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 43cd699

Please sign in to comment.