NACA airfoil max. camber as opti.variable #110
-
Dear @peterdsharpe and colleagues, I'm trying to optimize wing camber distribution along it span. I'm using asb.VortexLatticeMethod to evaluate wing CL and CDi. But there is a problem when I set max_camber of NACA as opti.variable. I get the error message shown below. So I'm wondering if this is implemented in AeroSandBox? (It worked fine when I used wing twist as opti.variable).
My code is as follows:
Thanks. Kind regards, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey Jan, Thanks for writing in! A good question. CauseThe high-level cause of this error is that:
Solution for Immediate ProblemFirst, for the immediate question - the fix here is to use Implemented, the fixed code looks like: import aerosandbox as asb
import aerosandbox.numpy as np
af_thickness_mode = asb.Airfoil(
name="NACA Thickness",
coordinates=asb.geometry.airfoil.airfoil_families.get_NACA_coordinates(max_camber=0, camber_loc=0.5, thickness=0.1)
).to_kulfan_airfoil()
af_camber_mode = asb.Airfoil(
name="NACA Camber",
coordinates=asb.geometry.airfoil.airfoil_families.get_NACA_coordinates(max_camber=0.01, camber_loc=0.5, thickness=0)
).to_kulfan_airfoil()
def get_aero(Nsa, camber, alpha):
# depsg = np.concatenate((0, depsg), axis=0)
xtip = 0 # m
ytip = 1.9 # m
ztip = 0 # m
croot = 0.6
ctip = 0.6
epsg = np.zeros(Nsa)
xmac = 0
cmac = 0.6
xsa = np.linspace(0, xtip, Nsa)
ysa = np.linspace(0, ytip, Nsa)
zsa = np.linspace(0, ztip, Nsa)
csa = np.linspace(croot, ctip, Nsa)
af = asb.KulfanAirfoil(
**{
k: camber / 0.01 * af_camber_mode.kulfan_parameters[k] + af_thickness_mode.kulfan_parameters[k]
for k in af_camber_mode.kulfan_parameters.keys()
}
)
aero_model = asb.Airplane(
name="Bwing",
xyz_ref=[xmac + 0.25 * cmac, 0, 0],
wings=[
asb.Wing(
name="Wing",
xyz_le=[0, 0, 0],
symmetric=True,
xsecs=[
asb.WingXSec(
xyz_le=[xsa[i], ysa[i], zsa[i]],
chord=csa[i],
twist=epsg[i],
airfoil=af
) for i in range(Nsa)
]
)
]
)
vlm = asb.VortexLatticeMethod( # NOTE: Recommend substituting this for asb.LiftingLine for this particular problem
airplane=aero_model,
op_point=asb.OperatingPoint(
velocity=21.3, # m/s
alpha=alpha # degree
),
spanwise_resolution=3,
spanwise_spacing_function=np.linspace,
verbose=True
)
return vlm.run()
def main():
print(asb.__version__)
Nsa = 9
CLw = 0.609
opti = asb.Opti()
alpha = opti.variable(init_guess=5.3, lower_bound=2., upper_bound=9.)
camber_init = 0.02 # * np.ones((Nsa,))
camber_lo = 0.02 # np.ones((Nsa,)) * 0.02
camber_up = 0.08 # np.ones((Nsa,)) * 0.08
camber_sec = opti.variable(init_guess=camber_init, lower_bound=camber_lo, upper_bound=camber_up)
aero = get_aero(Nsa, camber_sec, alpha)
opti.subject_to(aero["CL"] == CLw)
opti.minimize((-1 * aero["CL"] ** 3 / 2) / aero["CD"])
# opti.set_value()
sol = opti.solve(max_iter=15, behavior_on_failure="return_last")
print(sol.value(camber_sec))
print(sol.value(alpha))
return
if __name__ == "__main__":
print("Running test")
main() Basically what we're doing here is pre-computing Kulfan-parameterized airfoil mode shapes representing "thickness" and "camber", then linearly combining them to achieve the desired NACA airfoil shape. Finally, on a physics level, you may want to substitute Notes for ASB DevsFrom this issue, there are a few actionable outcomes the team can work on:
|
Beta Was this translation helpful? Give feedback.
Hey Jan,
Thanks for writing in! A good question.
Cause
The high-level cause of this error is that:
asb.VortexLatticeMethod
,asb.LiftingLine
, and similar aero analyses need to discretize the wing geometry to work (i.e., make a surface mesh).asb.Airfoil
object), this meshing logic currently needs to be able to identify which index of the airfoil coordinates array is the leading edge.asb.Airfoil.coordinates
variable is an optimization variable (as opposed to a non-changing NumPy array), the solver can't "guarantee" that the leading edge index won't change throughout airfoil shape optimization as coordinates move aro…