Skip to content

Commit

Permalink
Added dict key validation & updated documentation (#417)
Browse files Browse the repository at this point in the history
* chord-related fixes

* for black

* fixing RTD config

* added key validation for mesh_dict

* added key validation for surface dict

* removed unused keys from the tests

* updated surface dict doc page

* flake8

* fixed docs

* typo
  • Loading branch information
kanekosh authored Oct 8, 2023
1 parent f2f974f commit afcc73f
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 27 deletions.
1 change: 0 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ python:
path: .
extra_requirements:
- docs
system_packages: true
50 changes: 49 additions & 1 deletion openaerostruct/docs/user_reference/mesh_surface_dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,42 @@ The surface dict will be provided to Groups, including ``Geometry``, ``AeroPoint
- 3D ndarray
- m
- ``x, y, z`` coordinates of the mesh vertices, can be created by ``generate_mesh``.
* - span
- 10.0
- m
- Wing span.
* - taper
- 0.5
-
- Wing taper ratio.
* - sweep
- 10.0
- deg
- Wing sweep angle.
* - dihedral
- 5.0
- deg
- Wing dihedral.
* - twist_cp
- np.array([0, 5])
- deg
- B-spline control points for twist distribution. Array convention is ``[wing tip, ..., root]`` in symmetry cases, and ``[tip, ..., root, ... tip]`` when ``symmetry = False``.
* - chord_cp
- np.array([0.1, 5])
-
- B-spline control points for chord distribution. This is a chord scaler applied to the initial mesh, not the chord value [m] itself. Array convention is the same as ``twist_cp``.
* - xshear_cp
- np.array([0.1, 0.2])
- m
- B-spline control points for the x-wise shear deformation of the wing.
* - yshear_cp
- np.array([0.1, 0.2])
- m
- B-spline control points for the y-wise shear deformation of the wing.
* - zshear_cp
- np.array([0.1, 0.2])
- m
- B-spline control points for chord distribution. Array convention is the same than ``twist_cp``.
- B-spline control points for the z-wise shear deformation of the wing.
* - ref_axis_pos
- 0.25
-
Expand Down Expand Up @@ -240,6 +268,10 @@ The surface dict will be provided to Groups, including ``Geometry``, ``AeroPoint
- 0.12
-
- Thickness-over-chord ratio of airfoil provided for the wingbox cross-section.
* - strength_factor _for_upper_skin
- 1.0
-
- A factor to adjust the yield strength of the upper skin relative to the lower skin.
* - data_x_upper
- 1D ndarray
-
Expand All @@ -257,5 +289,21 @@ The surface dict will be provided to Groups, including ``Geometry``, ``AeroPoint
-
- ``y`` coordinates of the wingbox cross-section's lower surface

.. list-table:: FFD parameters
:widths: 20 20 5 55
:header-rows: 1

* - Key
- Example value
- Units
- Description
* - mx
- 2
-
- Number of the FFD control points in the x direction.
* - my
- 2
-
- Number of the FFD control points in the y direction.
..
TODO: list default values (if any), and whethre each key is required or optional.
2 changes: 1 addition & 1 deletion openaerostruct/examples/drag_polar_ground_effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def compute_drag_polar_ground_effect(Mach, alphas, heights, surfaces, trimmed=Fa
"wing_type": "rect",
"symmetry": True,
"span": 12.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 0.0,
}
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/examples/rectangular_wing/drag_polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/examples/rectangular_wing/mphys_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def setup(self):
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down
5 changes: 3 additions & 2 deletions openaerostruct/examples/rectangular_wing/opt_chord.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down Expand Up @@ -105,8 +105,9 @@
prob.driver.options["debug_print"] = ["nl_cons", "objs", "desvars"]

# Setup problem and add design variables, constraint, and objective
# wing.chord_cp is the chord scaling applied to the initial mesh
prob.model.add_design_var("alpha", lower=-10.0, upper=15.0)
prob.model.add_design_var("wing.chord_cp", lower=1e-3, upper=5.0)
prob.model.add_design_var("wing.chord_cp", lower=1e-3, upper=5.0, units=None)
prob.model.add_constraint(point_name + ".wing_perf.CL", equals=0.5)
prob.model.add_constraint(point_name + ".wing.S_ref", equals=10.0)
prob.model.add_objective(point_name + ".wing_perf.CD", scaler=1e4)
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/examples/rectangular_wing/opt_twist.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/examples/rectangular_wing/run_rect_wing.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/examples/rectangular_wing/run_roll.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"wing_type": "rect",
"symmetry": False,
"span": 9.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 1.0,
"chord_cos_spacing": 1.0,
}
Expand Down
8 changes: 6 additions & 2 deletions openaerostruct/geometry/geometry_group.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np

import openmdao.api as om
from openaerostruct.utils.check_surface_dict import check_surface_dict_keys


class Geometry(om.Group):
Expand All @@ -23,6 +24,9 @@ def initialize(self):
def setup(self):
surface = self.options["surface"]

# key validation of the surface dict
check_surface_dict_keys(surface)

# Get the surface name and create a group to contain components
# only for this surface
ny = surface["mesh"].shape[1]
Expand Down Expand Up @@ -91,10 +95,10 @@ def setup(self):
promotes_inputs=["chord_cp"],
promotes_outputs=["chord"],
)
comp.add_spline(y_cp_name="chord_cp", y_interp_name="chord", y_units="m")
comp.add_spline(y_cp_name="chord_cp", y_interp_name="chord", y_units=None)
bsp_inputs.append("chord")
if surface.get("chord_cp_dv", True):
self.set_input_defaults("chord_cp", val=surface["chord_cp"], units="m")
self.set_input_defaults("chord_cp", val=surface["chord_cp"], units=None)

if "t_over_c_cp" in surface.keys():
n_cp = len(surface["t_over_c_cp"])
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/geometry/geometry_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class GeometryMesh(om.Group):
twist[ny] : numpy array
1-D array of rotation angles for each wing slice in degrees.
chord_dist[ny] : numpy array
Chord length for each panel edge.
Spanwise distribution of the chord scaler.
taper : float
Taper ratio for the wing; 1 is untapered, 0 goes to a point at the tip.
Expand Down
4 changes: 2 additions & 2 deletions openaerostruct/geometry/geometry_mesh_transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class ScaleX(om.ExplicitComponent):
mesh[nx, ny, 3] : numpy array
Nodal mesh defining the initial aerodynamic surface.
chord[ny] : numpy array
Chord length for each panel edge.
Spanwise distribution of the chord scaler.
Returns
-------
Expand All @@ -147,7 +147,7 @@ def setup(self):
mesh_shape = self.options["mesh_shape"]
val = self.options["val"]
self.ref_axis_pos = self.options["ref_axis_pos"]
self.add_input("chord", units="m", val=val)
self.add_input("chord", units=None, val=val)
self.add_input("in_mesh", shape=mesh_shape, units="m")

self.add_output("mesh", shape=mesh_shape, units="m")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,40 @@ def test_scalex_ref_axis_trailing_edge(self):
# If chord_scaling_pos = 1, TE should not move
assert_near_equal(mesh[-1, :, :], prob["comp.mesh"][-1, :, :], tolerance=1e-10)

def test_scalex_chord_value(self):
# test actual chord value of a rectangular wing

mesh_dict = {
"num_y": 5,
"num_x": 3,
"wing_type": "rect",
"symmetry": True,
"span": 2.0,
"root_chord": 0.2,
}
mesh_in = generate_mesh(mesh_dict)

# initial chord
chord_in = mesh_in[-1, 0, 0] - mesh_in[0, 0, 0] # TE - LE

prob = om.Problem()
group = prob.model
comp = ScaleX(val=np.ones(3), mesh_shape=mesh_in.shape)
group.add_subsystem("comp", comp)

prob.setup()
chord_scaling = 1.3
prob.set_val("comp.chord", val=chord_scaling, units=None) # apply chord scaling factor
prob.set_val("comp.in_mesh", val=mesh_in, units="m")

prob.run_model()

# chord after manipulation
mesh_out = prob.get_val("comp.mesh", units="m")
chord_out = mesh_out[-1, 0, 0] - mesh_out[0, 0, 0] # TE - LE

assert_near_equal(chord_in * chord_scaling, chord_out, tolerance=1e-10)

def test_sweep(self):
symmetry = False
mesh = get_mesh(symmetry)
Expand Down
4 changes: 2 additions & 2 deletions openaerostruct/geometry/tests/test_vsp_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_full(self):
"wing_type": "rect",
"symmetry": False,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 0.0,
}

Expand All @@ -44,7 +44,7 @@ def test_symm(self):
"wing_type": "rect",
"symmetry": True,
"span": 10.0,
"chord": 1,
"root_chord": 1,
"span_cos_spacing": 0.0,
}

Expand Down
36 changes: 33 additions & 3 deletions openaerostruct/geometry/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
from numpy import cos, sin, tan
import warnings

# openvsp python interface
try:
Expand Down Expand Up @@ -94,7 +95,7 @@ def scale_x(mesh, chord_dist):
mesh[nx, ny, 3] : numpy array
Nodal mesh defining the initial aerodynamic surface.
chord_dist[ny] : numpy array
Chord length for each panel edge.
Spanwise distribution of the chord scaler.
Returns
-------
Expand Down Expand Up @@ -636,12 +637,39 @@ def get_default_geo_dict():
def generate_mesh(input_dict):
# Get defaults and update surface with the user-provided input
surf_dict = get_default_geo_dict()

# Warn if a user provided a key that is not implemented
user_defined_keys = input_dict.keys()
for key in user_defined_keys:
if key not in surf_dict:
warnings.warn(
"Key `{}` in mesh_dict is not implemented and will be ignored".format(key),
category=RuntimeWarning,
stacklevel=2,
)
# Warn if a user did not define important keys
for key in ["num_x", "num_y", "wing_type", "symmetry"]:
if key not in user_defined_keys:
warnings.warn(
"Missing `{}` in mesh_dict. The default value of {} will be used.".format(key, surf_dict[key]),
category=RuntimeWarning,
stacklevel=2,
)

# Apply user-defined options
surf_dict.update(input_dict)

# Warn if a user defined span and root_chord for CRM
if surf_dict["wing_type"] == "CRM":
if "span" in user_defined_keys or "root_chord" in user_defined_keys:
warnings.warn(
"`span` and `root_chord` in mesh_dict will be ignored for the CRM wing.",
category=RuntimeWarning,
stacklevel=2,
)

num_x = surf_dict["num_x"]
num_y = surf_dict["num_y"]
span = surf_dict["span"]
chord = surf_dict["root_chord"]
span_cos_spacing = surf_dict["span_cos_spacing"]
chord_cos_spacing = surf_dict["chord_cos_spacing"]

Expand All @@ -655,6 +683,8 @@ def generate_mesh(input_dict):

# Generate rectangular mesh
if surf_dict["wing_type"] == "rect":
span = surf_dict["span"]
chord = surf_dict["root_chord"]
mesh = gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing, chord_cos_spacing)

# Generate CRM mesh. Note that this outputs twist information
Expand Down
4 changes: 4 additions & 0 deletions openaerostruct/integration/aerostruct_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from openaerostruct.aerodynamics.compressible_states import CompressibleVLMStates
from openaerostruct.structures.tube_group import TubeGroup
from openaerostruct.structures.wingbox_group import WingboxGroup
from openaerostruct.utils.check_surface_dict import check_surface_dict_keys

import openmdao.api as om

Expand All @@ -26,6 +27,9 @@ def setup(self):
DVGeo = self.options["DVGeo"]
connect_geom_DVs = self.options["connect_geom_DVs"]

# key validation of the surface dict
check_surface_dict_keys(surface)

geom_promotes_in = []
geom_promotes_out = ["mesh"]

Expand Down
2 changes: 0 additions & 2 deletions openaerostruct/tests/test_aero_atmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ def test(self):
"fem_model_type": "tube",
"twist_cp": twist_cp,
"mesh": mesh,
"num_x": mesh.shape[0],
"num_y": mesh.shape[1],
# Aerodynamic performance of the lifting surface at
# an angle of attack of 0 (alpha=0).
# These CL0 and CD0 values are added to the CL and CD
Expand Down
1 change: 0 additions & 1 deletion openaerostruct/tests/test_simple_rect_aero.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test(self):
surf_dict = {
# Wing definition
"name": "wing", # name of the surface
"type": "aero",
"symmetry": True, # if true, model one half of wing
# reflected across the plane y = 0
"S_ref_type": "wetted", # how we compute the wing area,
Expand Down
1 change: 0 additions & 1 deletion openaerostruct/tests/test_simple_rect_aero_roll.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test(self):
surf_dict = {
# Wing definition
"name": "wing", # name of the surface
"type": "aero",
"symmetry": False, # if true, model one half of wing
# reflected across the plane y = 0
"S_ref_type": "wetted", # how we compute the wing area,
Expand Down
1 change: 0 additions & 1 deletion openaerostruct/tests/test_simple_rect_aero_sideslip.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test(self):
surf_dict = {
# Wing definition
"name": "wing", # name of the surface
"type": "aero",
"symmetry": False, # if true, model one half of wing
# reflected across the plane y = 0
"S_ref_type": "wetted", # how we compute the wing area,
Expand Down
1 change: 0 additions & 1 deletion openaerostruct/tests/test_simple_rect_aero_wo_symmetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test(self):
surf_dict = {
# Wing definition
"name": "wing", # name of the surface
"type": "aero",
"symmetry": False, # if true, model one half of wing
# reflected across the plane y = 0
"S_ref_type": "wetted", # how we compute the wing area,
Expand Down
Loading

0 comments on commit afcc73f

Please sign in to comment.