Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions examples/run_opt_camber_ga.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,47 @@ def main():
baseline_coeffs = np.array([0.02, 0.0])
baseline_cambers = quadratic_camber_distribution(baseline_coeffs, Y_POSITIONS)
incidences = linear_incidence_distribution(Y_POSITIONS)
create_avl_file_with_naca_airfoils(baseline_cambers, incidences, TEMP_AVL_FILE)

geom_dict = {
"title": "AIRCRAFT", # Aicraft name (MUST BE SET)
"mach": 0.0, # Reference Mach number
"iysym": 0, # y-symmetry settings
"izsym": 0, # z-symmetry settings
"zsym": 0.0, # z-symmetry plane
"Sref": 0.8127, # Reference planform area
"Cref": 0.2286, # Reference chord area
"Bref": 3.556, # Reference span length
"XYZref": np.array([0.0, 0, 0]), # Reference x,y,z position
"CDp": 0.0, # Reference profile drag adjustment
"surfaces": { # dictionary of surface dictionaries
"Wing": {
# General
"num_sections": NUM_SECTIONS, # number of sections in surface
"num_controls": np.array([0]*NUM_SECTIONS), # number of control surfaces assocaited with each section (in order)
"num_design_vars": np.array([0]*NUM_SECTIONS), # number of AVL design variables assocaited with each section (in order)
"component": 1, # logical surface component index (for grouping interacting surfaces, see AVL manual)
"yduplicate": 0.0, # surface is duplicated over the ysymm plane
"xles": np.zeros(NUM_SECTIONS), # leading edge cordinate vector(x component)
"yles": np.linspace(0, Y_TIP, NUM_SECTIONS), # leading edge cordinate vector(y component)
"zles": np.zeros(NUM_SECTIONS), # leading edge cordinate vector(z component)
"chords": np.ones(NUM_SECTIONS)*0.2286, # chord length vector
"aincs": incidences, # incidence angle vector
# NACA
'naca' : np.array(['2412']*NUM_SECTIONS), # 4-digit NACA airfoil
# Paneling
"nchordwise": 8, # number of chordwise horseshoe vortice s placed on the surface
"cspace": 1.0, # chordwise vortex spacing parameter
"nspan": 20, # number of spanwise horseshoe vortices placed on the entire surface
"sspace": -2.0, # spanwise vortex spacing parameter for entire surface
"nspans": np.array([5]*NUM_SECTIONS), # number of spanwise elements vector
"sspaces": np.array([3.0]*NUM_SECTIONS), # spanwise spacing vector (for each section)
"use surface spacing": 1, # surface spacing set for the entire surface (known as LSURFSPACING in AVL)
},
}
}

# Initialize solver ONCE - this will be reused throughout optimization
ovl = OVLSolver(geo_file=TEMP_AVL_FILE, debug=DEBUG)
ovl = OVLSolver(input_dict=geom_dict, debug=DEBUG)
ovl.set_constraint('alpha', None, TRIM_AOA)
ovl.set_parameter('velocity', TRIM_VELOCITY)
ovl.execute_run()
Expand Down
46 changes: 28 additions & 18 deletions optvl/optvl_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,22 +640,23 @@ def get_types_from_blk(common_blk):
if last_char == "C":
return str
elif last_char == "R":
return (float, np.float64)
return (np.float64, float)
elif last_char == "I":
return (int, np.int32)
return (np.int32, int)
elif last_char == "L":
return (bool, int, np.int32)
else:
raise ValueError(f"type not able to be infered from common block {common_blk}")

def check_type(key, avl_vars, given_val):
"""Checks the type for a given AVL Fortran Common Block var against a given value
def check_type(key, avl_vars, given_val, cast_type=True):
"""Checks the type for a given AVL Fortran Common Block var against a given value.
If the type can be cast into the correct type then it is and returned

Args:
key: OptVL input variable dictionary key
avl_vars: AVL Common Block variable name array
given_val: Input value to check type against

cast_type: Flag to cast the type into the required type if possible
"""
# get the type that it should be
expected_type = get_types_from_blk(avl_vars[0])
Expand Down Expand Up @@ -687,15 +688,24 @@ def check_type(key, avl_vars, given_val):

# check that the type of the array matches the expectation
if not isinstance(given_val.flatten()[0], expected_type):
raise TypeError(
f"Variable {key} is an array of type {given_val.dtype} but expected {expected_type}"
)
if cast_type and np.can_cast(given_val.dtype, expected_type[0], casting='same_kind'):
given_val = given_val.astype(np.dtype(expected_type[0]))
else:
raise TypeError(
f"Variable {key} is an array of type {given_val.dtype} but expected {expected_type}"
)
else:
# check the type of the scaler
if not isinstance(given_val, expected_type):
raise TypeError(
f"Variable {key} is a scalar of type {type(given_val)} but expected {expected_type}"
)
if cast_type and np.can_cast(given_val.dtype, expected_type[0], casting='same_kind'):
given_val = np.dtype(expected_type[0]).type(given_val)
else:
raise TypeError(
f"Variable {key} is a scalar of type {type(given_val)} but expected {expected_type}"
)


return given_val

# Set AVL header variables
# CDp is the only optional input for the AVL header
Expand All @@ -710,7 +720,7 @@ def check_type(key, avl_vars, given_val):
else:
val = input_dict[key]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)

self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val)

Expand Down Expand Up @@ -829,7 +839,7 @@ def check_type(key, avl_vars, given_val):
else:
val = surf_dict[key]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)

self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val, slicer=avl_vars[2])

Expand All @@ -842,7 +852,7 @@ def check_type(key, avl_vars, given_val):
f"OptVL can only have one method of specifing airfoil geometry per surface, found {airfoil_spec_keys} in surface {surf_name}"
)

xfminmax_arr = surf_dict.get("xfminmax", np.array([0.0, 1.0] * num_secs))
xfminmax_arr = surf_dict.get("xfminmax", np.tile([0.0, 1.0], (num_secs, 1)))
num_pts = min(50, self.IBX)

# setup for manually specifying coordinates
Expand Down Expand Up @@ -881,7 +891,7 @@ def check_type(key, avl_vars, given_val):

val = surf_dict[key][j]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)
self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val, slicer=avl_vars[2])

# 4 digit NACA airfoil specification
Expand Down Expand Up @@ -946,7 +956,7 @@ def check_type(key, avl_vars, given_val):
else:
val = surf_dict[key][j]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)
self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val, slicer=avl_vars[2])

# --- setup design variables for each section ---
Expand All @@ -968,7 +978,7 @@ def check_type(key, avl_vars, given_val):
else:
val = surf_dict[key][j]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)
self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val, slicer=avl_vars[2])

# Make the surface
Expand Down Expand Up @@ -1025,7 +1035,7 @@ def check_type(key, avl_vars, given_val):
else:
val = body_dict[key]

check_type(key, avl_vars, val)
val = check_type(key, avl_vars, val)

self.set_avl_fort_arr(avl_vars[0], avl_vars[1], val, slicer=avl_vars[2])

Expand Down
4 changes: 0 additions & 4 deletions src/ainput.f
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ SUBROUTINE INPUT(LUN,FNAME,FERR)
NSEC_B = 0
C
NSURF = 0
NSURFDUPL = 0
NVOR = 0
NSTRIP = 0
C
Expand Down Expand Up @@ -206,7 +205,6 @@ SUBROUTINE INPUT(LUN,FNAME,FERR)
IF(LDUPL(ISURF)) THEN
CALL SDUPL(ISURF,YDUPL(ISURF),'YDUP')
NSURF = NSURF + 1
NSURFDUPL = NSURFDUPL + 1
ENDIF
C
ISURF = 0
Expand Down Expand Up @@ -245,7 +243,6 @@ SUBROUTINE INPUT(LUN,FNAME,FERR)
IF(LDUPL(ISURF)) THEN
CALL SDUPL(ISURF,YDUPL(ISURF),'YDUP')
NSURF = NSURF + 1
NSURFDUPL = NSURFDUPL + 1
ENDIF
C
ISURF = 0
Expand Down Expand Up @@ -331,7 +328,6 @@ SUBROUTINE INPUT(LUN,FNAME,FERR)
IF(LDUPL(ISURF)) THEN
CALL SDUPL(ISURF,YDUPL(ISURF),'YDUP')
NSURF = NSURF + 1
NSURFDUPL = NSURFDUPL + 1
ENDIF
C
ISURF = 0
Expand Down
6 changes: 6 additions & 0 deletions src/amake.f
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,12 @@ subroutine update_surfaces()
NVOR = 0

ISURF = 1

NSURFDUPL = 0
do ii=1,(NSURF)
if (ldupl(ii)) NSURFDUPL = NSURFDUPL + 1
enddo

c the iterations of this loop are not independent because we count
c up the size information as we make each surface
do ii=1,(NSURF-NSURFDUPL)
Expand Down
Loading