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
2 changes: 2 additions & 0 deletions config/defaults/config.LINUX_GFORTRAN.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ F2PY = f2py
F2PY_FF90 = gfortran

PYTHON = python

LINKER_FLAGS =
40 changes: 27 additions & 13 deletions docs/making_a_script.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,48 @@ Like AVL, you can also add a mass file as well.
ovl = OVLSolver(geo_file="aircraft.avl", mass_file="aircraft.mass")
```


## Constraints
## Setting variables and control deflections
After initializing, you can set up various constraints directly.
You can set `alpha`, `beta`, `roll rate`, `pitch rate`, and `yaw rate` as well as any control surface in this way.

```python
ovl.set_constraint("alpha", 0.00)
ovl.set_variable("alpha", 0.00)
```
You can also set the deflection of any control surface for a run.
The control surfaces are specified using the names in the geometry file.
```python
ovl.set_control_deflection("Elevator", 0.00)
```

## Setting parameters
You can also set parameters of the run case.
The list of parameters you can set are `CD0`, `bank`, `elevation`, `heading`, `Mach`, `velocity`, `density`, `grav.acc.`, `turn rad.`, `load fac.`, `X cg`, `Y cg`, `Z cg`, `mass`, `Ixx`, `Iyy`, `Izz`, `Ixy`, `Iyz`, `Izx`, `visc CL_a`, `visc CL_u`, `visc Cm_a`, `visc Cm_u`,
```python
# set the flow parameters like mach numbers
ovl.set_parameter("Mach", 0.3)
```


## Setting constraints
You can also set a variable in order to meet a specific constraint value.
The valid constraint options are `CL`, `CY`, `Cl roll moment`, `Cm pitch moment`, `Cn yaw moment`.
The valid constraint options are `CL`, `CY`, `Cl`, `Cm`, `Cn`.
The roll moment coefficients have lower case letters just like in AVL.

!!! Warning
Note the difference in capitalization between the coefficient of lift, CL, and the roll moment coefficient, `Cl`.

!!! Warning
Be careful to state a constraint variable, `con_var`, that is affected by the input. For example if you accidentally specify that the pitching moment should be trimmed by the rudder the analysis will not converge.
Be careful to state a constraint variable that is affected by the input. For example if you accidentally specify that the pitching moment should be trimmed by the rudder the analysis will not converge.

```python
# set the Elevator to trim Cm to zero
ovl.set_constraint("Elevator", 0.00, con_var="Cm pitch moment")
ovl.set_constraint("alpha", "CL", 0.5)
# set the Elevator to trim Cm to zero
ovl.set_constraint("Elevator", "Cm", 0.00)
# set the Rudder to trim Cn to zero
ovl.set_constraint("Rudder", 0.00, con_var="Cn yaw moment")
ovl.set_constraint("Rudder", "Cn", 0.00)
```

You can also set parameters of the run case.
The list of parameters you can set are `CD0`, `bank`, `elevation`, `heading`, `Mach`, `velocity`, `density`, `grav.acc.`, `turn rad.`, `load fac.`, `X cg`, `Y cg`, `Z cg`, `mass`, `Ixx`, `Iyy`, `Izz`, `Ixy`, `Iyz`, `Izx`, `visc CL_a`, `visc CL_u`, `visc CM_a`, `visc CM_u`,
```python
# set the flow parameters like mach numbers
ovl.set_parameter("Mach", 0.3)
```

## Running Analysis

Expand Down
2 changes: 1 addition & 1 deletion docs/optimization_setup_om.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ To turn on other inputs such as the reference values and case parameters, use th
```python
model.add_subsystem("ovlsolver", OVLGroup(geom_file="aircraft.avl",input_param_vals=True, input_ref_vals=True))
```
The force coefficients such as `CL`, `CD`, and `CM` are automatically added as outputs.
The force coefficients such as `CL`, `CD`, and `Cm` are automatically added as outputs.
To add stability derivatives or control surface derivatives as outputs, just use the `output_stability_derivs` and `output_con_surf_derivs` keyword arguments to the group to turn them on.
```python
model.add_subsystem("ovlsolver", OVLGroup(geom_file="aircraft.avl", output_stability_derivs=True, output_con_surf_derivs=True))
Expand Down
34 changes: 12 additions & 22 deletions docs/optimization_setup_scipy.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,24 @@ To use SciPy's SLSQP, we will need to supply it with custom objective and constr
These functions need to take in the design variables and apply them to our OptVL solver.
The snippet below provides an example of an objective function.
```python
def objective_function(x):
ovl.set_constraint("Elevator", x[0])
ovl.set_surface_params({"Wing":{"aincs":x[1:]}})

ovl.execute_run()
cd = ovl.get_total_forces()['CD']
print(x, cd)

return cd
{%
include-markdown "../examples/run_opt_scipy.py"
start="# obj-start"
end="# obj-end"
%}
```

Note: the objective function is specified by the return value of the function.
If you wanted to save data about each iteration or write output, the objective function would be a good place to add that functionality.
To supply the gradient information to SLSQP, we have to define another function that returns the gradients for a given design variable vector.
```python
def objective_gradient(x):
# Partial derivatives of the objective_function
ovl.set_constraint("Elevator", x[0])
ovl.set_surface_params({"Wing":{"aincs":x[1:]}})

ovl.execute_run()

sens = ovl.execute_run_sensitivities(['CD'])
dcd_dele = sens['CD']['Elevator']
dcd_daincs = sens['CD']['Wing']['aincs']

# concatinate the two and return the derivs
return np.concatenate(([dcd_dele], dcd_daincs))
{%
include-markdown "../examples/run_opt_scipy.py"
start="# objgrad-start"
end="# objgrad-end"
%}
```

The function `ovl.execute_run_sensitivities(['CD'])` does all the necessary work to compute the derivatives for the given list of functions.
We just need to parse the `sens` dictionary for the derivatives with respect to the design variables we are interested in.

Expand Down
6 changes: 3 additions & 3 deletions docs/optvl_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ The commands from the oper and mode menus are available

|action| AVL's "OPER" command| OptVL API call|
|-----|--|--|
|setting the angle of attack|a a <angle>| ovl.set_constraint("alpha", <angle>)|
| set variable such that constraint = val | <variable> <constraint> <val> | ovl.set_constraint(<variable>, <val>, con_var=<constraint>) |
| set CL constraint| c1; c 1.3| ovl.set_trim_condition("CL", 1.3)|
|setting the angle of attack|a a <angle>| ovl.set_variable("alpha", <angle>)|
| set variable such that constraint = val | <variable> <constraint> <val> | ovl.set_constraint(<variable>, <constraint>, <val>) |
| set CL constraint| c1; c 1.3| ovl.set_constraint("alpha","CL", <val>) or ovl.set_trim_condition("CL", 1.3)|
| run an analysis | x | ovl.execute_run() |
| after an analysis | FT | ovl.get_total_forces() |
| get strip force data | ST | ovl.get_strip_forces() |
Expand Down
2 changes: 1 addition & 1 deletion docs/pyavl_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The table below lists the changes.
| `set_case_parameter` | `set_parameter` |
| `get_case_constraint` | `get_constraint` |
| `get_strip_data` | `get_strip_forces` |
| `add_constraint` | `set_constraint` |
| `add_constraint` | split into `set_constraint`, `set_variable`, `set_control_deflection`|
| `add_trim_condition` | `set_trim_condition` |
| `executeRun` | use `execute_run` instead |

Expand Down
2 changes: 1 addition & 1 deletion examples/plot_aircraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
ovl_solver = OVLSolver(geo_file="aircraft.avl", debug=False)
ovl_solver.plot_geom()

ovl_solver.set_constraint("alpha", 5.00)
ovl_solver.set_variable("alpha", 5.00)
ovl_solver.execute_run()

ovl_solver.plot_cp()
Expand Down
2 changes: 1 addition & 1 deletion examples/plot_planform_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
driver_cases = cr.list_cases('driver',out_stream=None)
obj_arr = np.zeros(len(driver_cases))
for idx_case in range(len(driver_cases)):
obj_arr[idx_case] = cr.get_case(driver_cases[idx_case])['glide.duration']
obj_arr[idx_case] = cr.get_case(driver_cases[idx_case])['glide.duration'][0]

plt.plot(obj_arr)
plt.xlabel('iteration')
Expand Down
8 changes: 4 additions & 4 deletions examples/plot_sectional_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import matplotlib.pyplot as plt

ovl = OVLSolver(geo_file="aircraft.avl", debug=False)
ovl.set_constraint('alpha', 5.0)
ovl.set_constraint('beta', 10.0)
ovl.set_variable('alpha', 5.0)
ovl.set_variable('beta', 10.0)
ovl.execute_run()

# keys-start
Expand Down Expand Up @@ -38,8 +38,8 @@
strip_data = ovl.get_strip_forces()
for surf_key in strip_data:
span_distance = strip_data[surf_key]['Y LE']
plt.plot(span_distance, strip_data[surf_key]['CN'], color='C0')
plt.plot(span_distance, strip_data[surf_key]['CR'], color='C1')
plt.plot(span_distance, strip_data[surf_key]['Cn'], color='C0')
plt.plot(span_distance, strip_data[surf_key]['Cl'], color='C1')

plt.legend(['roll distribution', 'yaw distribution'])
plt.title('roll and yaw spanwise data')
Expand Down
12 changes: 6 additions & 6 deletions examples/run_aero_sweeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
ovl = OVLSolver(geo_file="aircraft.avl", debug=False)

# set the angle of attack
ovl.set_constraint("alpha", 0.00)
ovl.set_variable("alpha", 0.00)

# set the deflection of the elevator to trim the pitching moment
ovl.set_constraint("Elevator", 0.00, con_var="Cm pitch moment")
ovl.set_constraint("Elevator", "Cm", 0.00)

ovl.set_parameter("Mach", 0.3)

Expand All @@ -16,26 +16,26 @@
print("----------------- alpha sweep ----------------")
print(" Angle Cl Cd Cdi Cdv Cm")
for alpha in range(10):
ovl.set_constraint("alpha", alpha)
ovl.set_variable("alpha", alpha)
ovl.execute_run()
run_data = ovl.get_total_forces()
print(
f' {alpha:10.6f} {run_data["CL"]:10.6f} {run_data["CD"]:10.6f} {run_data["CDi"]:10.6f} {run_data["CDv"]:10.6f} {run_data["Cm"]:10.6f}'
)

ovl.set_constraint("alpha", 0.00)
ovl.set_variable("alpha", 0.00)

print("----------------- beta sweep ----------------")
print(" Angle Cl Cd Cdi Cdv Cm")
for beta in range(10):
ovl.set_constraint("beta", beta)
ovl.set_variable("beta", beta)
ovl.execute_run()
run_data = ovl.get_total_forces()
print(
f' {beta:10.6f} {run_data["CL"]:10.6f} {run_data["CD"]:10.6f} {run_data["CDi"]:10.6f} {run_data["CDv"]:10.6f} {run_data["Cm"]:10.6f}'
)

ovl.set_constraint("beta", 0.00)
ovl.set_variable("beta", 0.00)

print("----------------- Mach sweep ----------------")
print(" Mach Cl Cd Cdi Cdv Cm")
Expand Down
2 changes: 1 addition & 1 deletion examples/run_analysis_body.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
print("----------------- alpha sweep ----------------")
print(" Angle Cl Cd Cdi Cdv Cm")
for alpha in range(10):
ovl_solver.set_constraint("alpha", alpha)
ovl_solver.set_variable("alpha", alpha)
ovl_solver.execute_run()
run_data = ovl_solver.get_total_forces()
print(
Expand Down
11 changes: 7 additions & 4 deletions examples/run_basic.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
from optvl import OVLSolver

ovl = OVLSolver(geo_file="aircraft.avl", debug=False)
ovl = OVLSolver(geo_file="aircraft.avl")

# look at the geometry to see that everything is right
ovl.plot_geom()

# set the angle of attack
ovl.set_constraint("alpha", 0.00)
ovl.set_variable("alpha", 1.23)
# modify the mach number
ovl.set_parameter("Mach", 0.3)

# set the deflection of the elevator to trim the pitching moment
ovl.set_constraint("Elevator", 0.00, con_var="Cm pitch moment")
ovl.set_constraint("Elevator", "Cm", 0.00)

ovl.set_control_deflection("Elevator", 10.0)

ovl.set_parameter("Mach", 0.3)

# This is the method that acutally runs the analysis
ovl.execute_run()
Expand Down
2 changes: 1 addition & 1 deletion examples/run_body_axis_derivs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ovl_solver = OVLSolver(geo_file="aircraft.avl", debug=False)
alpha = 3.0
ovl_solver.set_constraint("alpha", alpha)
ovl_solver.set_variable("alpha", alpha)
ovl_solver.execute_run()

derivs = ovl_solver.get_body_axis_derivs()
Expand Down
2 changes: 1 addition & 1 deletion examples/run_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
weight = mass * g
cl = weight / (0.5 * dens * vel**2)
ovl.set_trim_condition("CL", cl)
ovl.set_constraint("Elevator", 0.00, con_var="Cm pitch moment")
ovl.set_constraint("Elevator", "Cm", 0.00)

ovl.execute_eigen_mode_calc()

Expand Down
16 changes: 8 additions & 8 deletions examples/run_opt_clmax.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def objective_function(dvs):
Scipy's minimize function tries to minimize this value.
"""
alpha = dvs[0]
ovl_solver.set_constraint("alpha", alpha)
ovl_solver.set_variable("alpha", alpha)
def_elev = dvs[1]
ovl_solver.set_constraint("Elevator", def_elev)
ovl_solver.set_control_deflection("Elevator", def_elev)

ovl_solver.execute_run()

Expand All @@ -46,9 +46,9 @@ def cl_con(dvs):
Returns a value >= 0 if the constraint is met (1.75 - max_cl_sectional).
"""
alpha = dvs[0]
ovl_solver.set_constraint("alpha", alpha)
ovl_solver.set_variable("alpha", alpha)
def_elev = dvs[1]
ovl_solver.set_constraint("Elevator", def_elev)
ovl_solver.set_control_deflection("Elevator", def_elev)
ovl_solver.execute_run()

strip_forces = ovl_solver.get_strip_forces()
Expand All @@ -62,9 +62,9 @@ def cl_con(dvs):

def cm_con(dvs):
alpha = dvs[0]
ovl_solver.set_constraint("alpha", alpha)
ovl_solver.set_variable("alpha", alpha)
def_elev = dvs[1]
ovl_solver.set_constraint("Elevator", def_elev)
ovl_solver.set_control_deflection("Elevator", def_elev)
ovl_solver.execute_run()

cm = ovl_solver.get_total_forces()['Cm']
Expand Down Expand Up @@ -106,8 +106,8 @@ def cm_con(dvs):

# Verification run at the optimized alpha to double-check AVL results
print("\nVerification run at optimized alpha:")
ovl_solver.set_constraint("alpha", optimized_alpha)
ovl_solver.set_constraint("Elevator", optimized_def_elev)
ovl_solver.set_variable("alpha", optimized_alpha)
ovl_solver.set_control_deflection("Elevator", optimized_def_elev)


# Recalculate max sectional Cl at the optimal alpha for verification
Expand Down
2 changes: 1 addition & 1 deletion examples/run_opt_custom_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ def compute(self, inputs, outputs):
# prob.check_totals()


prob.model.ovlsolver.solver.avl.write_geom_file('opt_airplane.avl')
prob.model.ovlsolver.solver.ovl.write_geom_file('opt_airplane.avl')
17 changes: 11 additions & 6 deletions examples/run_opt_scipy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@
# setup OptVL
ovl_solver.set_parameter("Mach", 0.0)

# obj-start
# Define your custom objective function with outputs from OptVL
def objective_function(x):
ovl_solver.set_constraint("Elevator", x[0])
ovl_solver.set_control_deflection("Elevator", x[0])
ovl_solver.set_surface_params({"Wing":{"aincs":x[1:]}})

ovl_solver.execute_run()
cd = ovl_solver.get_total_forces()['CD']
print(x, cd)

return cd

# obj-end
# objgrad-start
def objective_gradient(x):
# Partial derivatives of the objective_function

# we are trusting that the design variables have already been applied
# and propogated through by the objective_function.

ovl_solver.set_constraint("Elevator", x[0])
ovl_solver.set_control_deflection("Elevator", x[0])
ovl_solver.set_surface_params({"Wing":{"aincs":x[1:]}})

ovl_solver.execute_run()
Expand All @@ -36,11 +38,12 @@ def objective_gradient(x):

# concatinate the two and return the derivs
return np.concatenate(([dcd_dele], dcd_daincs))
# objgrad-end


# eq-start
# Define equality constraint: h(x) = 0
def eq_constraint(x):
ovl_solver.set_constraint("Elevator", x[0])
ovl_solver.set_control_deflection("Elevator", x[0])
ovl_solver.set_surface_params({"Wing":{"aincs":x[1:]}})

ovl_solver.execute_run()
Expand All @@ -55,7 +58,8 @@ def eq_constraint(x):
cm_con = coeff['Cm'] - cm_target

return np.array([cl_con, cm_con])

# eq-end
# eqgrad-start
# Define the gradient of the equality constraint
def eq_constraint_jac(x):
sens = ovl_solver.execute_run_sensitivities(['CL', 'Cm'])
Expand All @@ -69,6 +73,7 @@ def eq_constraint_jac(x):

# concatinate the two and return the derivs
return np.array([dcl_dx, dcm_dx])
# eqgrad-end

num_sec = 5
# Initial guess for the variables
Expand Down
Loading
Loading