Skip to content

Commit 0448bff

Browse files
kanekosheytanadler
andauthored
Minor fix to mesh generator (#430)
* 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 <eytana@umich.edu>
1 parent d788e11 commit 0448bff

8 files changed

Lines changed: 59 additions & 47 deletions

File tree

.github/workflows/oas.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
test:
2121
runs-on: ubuntu-latest
2222
strategy:
23+
fail-fast: false # continue other jobs even if one of the jobs in matrix fails
2324
matrix:
2425
dep-versions: ["oldest", "latest"]
2526
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set versions to test here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -163,12 +164,13 @@ jobs:
163164
coverage xml
164165
165166
- name: Upload Coverage to Codecov
166-
uses: codecov/codecov-action@v3
167+
uses: codecov/codecov-action@v4
167168
with:
168169
fail_ci_if_error: true
169-
token: ${{ secrets.CODECOV_TOKEN }}
170170
verbose: true
171-
171+
env:
172+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
173+
172174
# --- linting and formatting ---
173175
black:
174176
uses: mdolab/.github/.github/workflows/black.yaml@main

openaerostruct/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.7.1"
1+
__version__ = "2.7.2"

openaerostruct/docs/user_reference/mesh_surface_dict.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Here is a list of the keys and default values of the ``mesh_dict``, which is use
1919
* - num_x
2020
- 3
2121
-
22-
- Number of chordwise vertices. Needs to be 2 or an odd number.
22+
- Number of chordwise vertices.
2323
* - num_y
2424
- 5
2525
-

openaerostruct/geometry/tests/test_vsp_mesh.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def test_full(self):
2727
"span": 10.0,
2828
"root_chord": 1,
2929
"span_cos_spacing": 0.0,
30+
"offset": [-0.5, 0, 0], # chordwise coordinate goes from -0.5 to 0.5
3031
}
3132

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

5153
oas_mesh = generate_mesh(mesh_dict)

openaerostruct/geometry/utils.py

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ def gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing=0.0, chord_cos_spa
375375
mesh = np.zeros((num_x, num_y, 3))
376376
ny2 = (num_y + 1) // 2
377377

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

399-
nx2 = (num_x + 1) // 2
400-
beta = np.linspace(0, np.pi / 2, nx2)
401-
402-
# mixed spacing with span_cos_spacing as a weighting factor
403-
# this is for the chordwise spacing
404-
cosine = 0.5 * np.cos(beta) # cosine spacing
405-
uniform = np.linspace(0, 0.5, nx2)[::-1] # uniform spacing
406-
half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
407-
full_wing_x = np.hstack((-half_wing[:-1], half_wing[::-1])) * chord
408-
409-
# Special case if there are only 2 chordwise nodes
410-
if num_x <= 2:
411-
full_wing_x = np.array([0.0, chord])
400+
# --- chordwise discretization ---
401+
cosine = 0.5 * (1 - np.cos(np.linspace(0, np.pi, num_x))) # cosine spacing from 0 to 1
402+
uniform = np.linspace(0, 1, num_x) # uniform spacing
403+
# mixed spacing with chord_cos_spacing as a weighting factor
404+
wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
405+
wing_x *= chord # apply chord length
412406

407+
# --- form 3D mesh array ---
413408
for ind_x in range(num_x):
414409
for ind_y in range(num_y):
415-
mesh[ind_x, ind_y, :] = [full_wing_x[ind_x], full_wing[ind_y], 0]
410+
mesh[ind_x, ind_y, :] = [wing_x[ind_x], full_wing[ind_y], 0]
416411

417412
return mesh
418413

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

558553
# Obtain mesh and num properties
559554
num_y = mesh.shape[1]
560-
nx2 = (num_x + 1) // 2
561-
562-
# Create beta, an array of linear sampling points to pi/2
563-
beta = np.linspace(0, np.pi / 2, nx2)
564-
565-
# Obtain the two spacings that we will use to blend
566-
cosine = 0.5 * np.cos(beta) # cosine spacing
567-
uniform = np.linspace(0, 0.5, nx2)[::-1] # uniform spacing
568-
569-
# Create half of the wing in the chordwise direction
570-
half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
571555

572-
if chord_cos_spacing == 0.0:
573-
full_wing_x = np.linspace(0, 1.0, num_x)
574-
575-
else:
576-
# Mirror this half wing into a full wing; offset by 0.5 so it goes 0 to 1
577-
full_wing_x = np.hstack((-half_wing[:-1], half_wing[::-1])) + 0.5
556+
# chordwise discretization
557+
cosine = 0.5 * (1 - np.cos(np.linspace(0, np.pi, num_x))) # cosine spacing from 0 to 1
558+
uniform = np.linspace(0, 1, num_x) # uniform spacing
559+
# mixed spacing with chord_cos_spacing as a weighting factor
560+
wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing) * uniform
578561

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

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

592575
return new_mesh
@@ -635,6 +618,29 @@ def get_default_geo_dict():
635618

636619

637620
def generate_mesh(input_dict):
621+
"""
622+
Generate an OAS mesh.
623+
624+
Parameters
625+
----------
626+
input_dict : dict
627+
Dictionary containing user-provided parameters for the surface definition.
628+
See the following for more information:
629+
https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/user_reference/mesh_surface_dict.html#mesh-dict
630+
631+
Returns
632+
-------
633+
mesh : numpy array
634+
Nodal coordinates defining the mesh.
635+
shape = (nx, ny, 3),
636+
where nx is the number of chordwise discretization nodes, ny is the number of spanwise discretization nodes.
637+
If input_dict["symmetry"] is True, mesh defines left half of wing.
638+
twist : numpy array, optional
639+
Only for CRM wing (input_dict["wing_type"] == "CRM").
640+
Twist values at the spanwise locations.
641+
642+
"""
643+
638644
# Get defaults and update surface with the user-provided input
639645
surf_dict = get_default_geo_dict()
640646

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

680-
# Check to make sure that an odd number of chordwise points (num_x) was provided
681-
if not num_x % 2 and not num_x == 2:
682-
raise ValueError("num_x must be an odd number.")
683-
684686
# Generate rectangular mesh
685687
if surf_dict["wing_type"] == "rect":
686688
span = surf_dict["span"]

openaerostruct/tests/test_multiple_rect.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ def test(self):
4444
}
4545

4646
# Create a dictionary to store options about the surface
47-
mesh_dict = {"num_y": 5, "num_x": 3, "wing_type": "rect", "symmetry": True, "offset": np.array([50, 0.0, 0.0])}
47+
mesh_dict = {
48+
"num_y": 5,
49+
"num_x": 3,
50+
"wing_type": "rect",
51+
"symmetry": True,
52+
"offset": np.array([49.5, 0.0, 0.0]),
53+
}
4854

4955
mesh = generate_mesh(mesh_dict)
5056

openaerostruct/tests/test_scaneagle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def test(self):
115115
indep_var_comp.add_output("W0", val=10.0, units="kg")
116116
indep_var_comp.add_output("speed_of_sound", val=322.2, units="m/s")
117117
indep_var_comp.add_output("load_factor", val=1.0)
118-
indep_var_comp.add_output("empty_cg", val=np.array([0.2, 0.0, 0.0]), units="m")
118+
indep_var_comp.add_output("empty_cg", val=np.array([0.35, 0.0, 0.0]), units="m")
119119

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

openaerostruct/tests/test_struct_point_masses.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class Test(unittest.TestCase):
1212
def test(self):
1313
# Create a dictionary to store options about the surface
14-
mesh_dict = {"num_y": 31, "wing_type": "rect", "span": 10, "symmetry": True}
14+
mesh_dict = {"num_y": 31, "num_x": 3, "wing_type": "rect", "span": 10, "symmetry": True}
1515

1616
mesh = generate_mesh(mesh_dict)
1717

@@ -48,7 +48,7 @@ def test(self):
4848

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

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

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

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

7474
mesh = generate_mesh(mesh_dict)
7575

@@ -106,7 +106,7 @@ def test_multiple_masses(self):
106106

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

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

111111
indep_var_comp.add_output("point_masses", val=point_masses, units="kg")
112112
indep_var_comp.add_output("point_mass_locations", val=point_mass_locations, units="m")

0 commit comments

Comments
 (0)