Skip to content

Commit

Permalink
Minor fix to mesh generator (#430)
Browse files Browse the repository at this point in the history
* modify mesh generator to accept even nx

* fixed ref of chordwise coordinate for rectangle wings

* vsp test fix

* formatting

* formatting

* minor edits to GHA yml

* Use newer codecov version in GHA

* Whack the chunk adaptation

* clean up

---------

Co-authored-by: Eytan Adler <[email protected]>
  • Loading branch information
kanekosh and eytanadler authored Jun 4, 2024
1 parent d788e11 commit 0448bff
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 47 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/oas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false # continue other jobs even if one of the jobs in matrix fails
matrix:
dep-versions: ["oldest", "latest"]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set versions to test here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -163,12 +164,13 @@ jobs:
coverage xml
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

# --- linting and formatting ---
black:
uses: mdolab/.github/.github/workflows/black.yaml@main
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.7.1"
__version__ = "2.7.2"
2 changes: 1 addition & 1 deletion openaerostruct/docs/user_reference/mesh_surface_dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Here is a list of the keys and default values of the ``mesh_dict``, which is use
* - num_x
- 3
-
- Number of chordwise vertices. Needs to be 2 or an odd number.
- Number of chordwise vertices.
* - num_y
- 5
-
Expand Down
2 changes: 2 additions & 0 deletions openaerostruct/geometry/tests/test_vsp_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def test_full(self):
"span": 10.0,
"root_chord": 1,
"span_cos_spacing": 0.0,
"offset": [-0.5, 0, 0], # chordwise coordinate goes from -0.5 to 0.5
}

oas_mesh = generate_mesh(mesh_dict)
Expand All @@ -46,6 +47,7 @@ def test_symm(self):
"span": 10.0,
"root_chord": 1,
"span_cos_spacing": 0.0,
"offset": [-0.5, 0, 0], # chordwise coordinate goes from -0.5 to 0.5
}

oas_mesh = generate_mesh(mesh_dict)
Expand Down
74 changes: 38 additions & 36 deletions openaerostruct/geometry/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ def gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing=0.0, chord_cos_spa
mesh = np.zeros((num_x, num_y, 3))
ny2 = (num_y + 1) // 2

# --- spanwise discretization ---
# Hotfix a special case for spacing bunched at the root and tips
if span_cos_spacing == 2.0:
beta = np.linspace(0, np.pi, ny2)
Expand All @@ -396,23 +397,17 @@ def gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing=0.0, chord_cos_spa
half_wing = cosine * span_cos_spacing + (1 - span_cos_spacing) * uniform
full_wing = np.hstack((-half_wing[:-1], half_wing[::-1])) * span

nx2 = (num_x + 1) // 2
beta = np.linspace(0, np.pi / 2, nx2)

# mixed spacing with span_cos_spacing as a weighting factor
# this is for the chordwise spacing
cosine = 0.5 * np.cos(beta) # cosine spacing
uniform = np.linspace(0, 0.5, nx2)[::-1] # uniform spacing
half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
full_wing_x = np.hstack((-half_wing[:-1], half_wing[::-1])) * chord

# Special case if there are only 2 chordwise nodes
if num_x <= 2:
full_wing_x = np.array([0.0, chord])
# --- chordwise discretization ---
cosine = 0.5 * (1 - np.cos(np.linspace(0, np.pi, num_x))) # cosine spacing from 0 to 1
uniform = np.linspace(0, 1, num_x) # uniform spacing
# mixed spacing with chord_cos_spacing as a weighting factor
wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
wing_x *= chord # apply chord length

# --- form 3D mesh array ---
for ind_x in range(num_x):
for ind_y in range(num_y):
mesh[ind_x, ind_y, :] = [full_wing_x[ind_x], full_wing[ind_y], 0]
mesh[ind_x, ind_y, :] = [wing_x[ind_x], full_wing[ind_y], 0]

return mesh

Expand Down Expand Up @@ -557,24 +552,12 @@ def add_chordwise_panels(mesh, num_x, chord_cos_spacing):

# Obtain mesh and num properties
num_y = mesh.shape[1]
nx2 = (num_x + 1) // 2

# Create beta, an array of linear sampling points to pi/2
beta = np.linspace(0, np.pi / 2, nx2)

# Obtain the two spacings that we will use to blend
cosine = 0.5 * np.cos(beta) # cosine spacing
uniform = np.linspace(0, 0.5, nx2)[::-1] # uniform spacing

# Create half of the wing in the chordwise direction
half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform

if chord_cos_spacing == 0.0:
full_wing_x = np.linspace(0, 1.0, num_x)

else:
# Mirror this half wing into a full wing; offset by 0.5 so it goes 0 to 1
full_wing_x = np.hstack((-half_wing[:-1], half_wing[::-1])) + 0.5
# chordwise discretization
cosine = 0.5 * (1 - np.cos(np.linspace(0, np.pi, num_x))) # cosine spacing from 0 to 1
uniform = np.linspace(0, 1, num_x) # uniform spacing
# mixed spacing with chord_cos_spacing as a weighting factor
wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform

# Obtain the leading and trailing edges
le = mesh[0, :, :]
Expand All @@ -586,7 +569,7 @@ def add_chordwise_panels(mesh, num_x, chord_cos_spacing):
new_mesh[-1, :, :] = te

for i in range(1, num_x - 1):
w = full_wing_x[i]
w = wing_x[i]
new_mesh[i, :, :] = (1 - w) * le + w * te

return new_mesh
Expand Down Expand Up @@ -635,6 +618,29 @@ def get_default_geo_dict():


def generate_mesh(input_dict):
"""
Generate an OAS mesh.
Parameters
----------
input_dict : dict
Dictionary containing user-provided parameters for the surface definition.
See the following for more information:
https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/user_reference/mesh_surface_dict.html#mesh-dict
Returns
-------
mesh : numpy array
Nodal coordinates defining the mesh.
shape = (nx, ny, 3),
where nx is the number of chordwise discretization nodes, ny is the number of spanwise discretization nodes.
If input_dict["symmetry"] is True, mesh defines left half of wing.
twist : numpy array, optional
Only for CRM wing (input_dict["wing_type"] == "CRM").
Twist values at the spanwise locations.
"""

# Get defaults and update surface with the user-provided input
surf_dict = get_default_geo_dict()

Expand Down Expand Up @@ -677,10 +683,6 @@ def generate_mesh(input_dict):
if not num_y % 2:
raise ValueError("num_y must be an odd number.")

# Check to make sure that an odd number of chordwise points (num_x) was provided
if not num_x % 2 and not num_x == 2:
raise ValueError("num_x must be an odd number.")

# Generate rectangular mesh
if surf_dict["wing_type"] == "rect":
span = surf_dict["span"]
Expand Down
8 changes: 7 additions & 1 deletion openaerostruct/tests/test_multiple_rect.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ def test(self):
}

# Create a dictionary to store options about the surface
mesh_dict = {"num_y": 5, "num_x": 3, "wing_type": "rect", "symmetry": True, "offset": np.array([50, 0.0, 0.0])}
mesh_dict = {
"num_y": 5,
"num_x": 3,
"wing_type": "rect",
"symmetry": True,
"offset": np.array([49.5, 0.0, 0.0]),
}

mesh = generate_mesh(mesh_dict)

Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/tests/test_scaneagle.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def test(self):
indep_var_comp.add_output("W0", val=10.0, units="kg")
indep_var_comp.add_output("speed_of_sound", val=322.2, units="m/s")
indep_var_comp.add_output("load_factor", val=1.0)
indep_var_comp.add_output("empty_cg", val=np.array([0.2, 0.0, 0.0]), units="m")
indep_var_comp.add_output("empty_cg", val=np.array([0.35, 0.0, 0.0]), units="m")

prob.model.add_subsystem("prob_vars", indep_var_comp, promotes=["*"])

Expand Down
8 changes: 4 additions & 4 deletions openaerostruct/tests/test_struct_point_masses.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class Test(unittest.TestCase):
def test(self):
# Create a dictionary to store options about the surface
mesh_dict = {"num_y": 31, "wing_type": "rect", "span": 10, "symmetry": True}
mesh_dict = {"num_y": 31, "num_x": 3, "wing_type": "rect", "span": 10, "symmetry": True}

mesh = generate_mesh(mesh_dict)

Expand Down Expand Up @@ -48,7 +48,7 @@ def test(self):

point_masses = np.array([[10.0]])

point_mass_locations = np.array([[1.0, -10.0, 0.0]])
point_mass_locations = np.array([[1.5, -10.0, 0.0]])

indep_var_comp.add_output("point_masses", val=point_masses, units="kg")
indep_var_comp.add_output("point_mass_locations", val=point_mass_locations, units="m")
Expand All @@ -69,7 +69,7 @@ def test(self):

def test_multiple_masses(self):
# Create a dictionary to store options about the surface
mesh_dict = {"num_y": 31, "wing_type": "rect", "span": 10, "symmetry": True}
mesh_dict = {"num_y": 31, "num_x": 3, "wing_type": "rect", "span": 10, "symmetry": True}

mesh = generate_mesh(mesh_dict)

Expand Down Expand Up @@ -106,7 +106,7 @@ def test_multiple_masses(self):

point_masses = np.array([[10.0, 20.0]])

point_mass_locations = np.array([[1.0, -1.0, 0.0], [1.0, -2.0, 0.0]])
point_mass_locations = np.array([[1.5, -1.0, 0.0], [1.5, -2.0, 0.0]])

indep_var_comp.add_output("point_masses", val=point_masses, units="kg")
indep_var_comp.add_output("point_mass_locations", val=point_mass_locations, units="m")
Expand Down

0 comments on commit 0448bff

Please sign in to comment.