Skip to content

Commit 5ebabd1

Browse files
authored
Adding get_tagged_indices to mphys wrapper (#414)
* Adding `get_tagged_indices` to mphys wrapper * flake/black formatting * Adding test * minor test edit * black edit * flake edit * flake edit * update docstring and add warning * update docstring and add warning * Updating CI with cython downgrade * Updating CI with cython downgrade * Using more recent version of cython 0.29
1 parent af05b30 commit 5ebabd1

4 files changed

Lines changed: 117 additions & 4 deletions

File tree

.github/workflows/oas.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
PYGEO_VERSION_OLDEST: ['1.6.0'] # latest is pulled from main branch, for some reason anything after 1.12.2 seg faults on the old build
3434
VSP_VERSION: ['3.27.1'] # used for both builds
3535
PETSC_VERSION_LATEST: ['3.19.1']
36+
CYTHON_VERSION: ['0.29.36'] # used for both builds
3637

3738
steps:
3839
- uses: actions/checkout@v2
@@ -117,6 +118,8 @@ jobs:
117118
export PETSC_DIR=`pwd`
118119
./configure --PETSC_ARCH=$PETSC_ARCH --download-fblaslapack
119120
make PETSC_DIR=$PETSC_DIR PETSC_ARCH=$PETSC_ARCH all
121+
# Cython 3.0.0 break petsc4py install
122+
pip install cython==${{ matrix.CYTHON_VERSION }}
120123
pip install petsc4py==${{ matrix.PETSC_VERSION_LATEST }}
121124
122125
# We need pySpline/pyGeo to run FFD tests.

openaerostruct/mphys/aero_builder.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
"""
44

55
import copy
6+
import warnings
67

78
import openmdao.api as om
89

9-
from openaerostruct.mphys.utils import get_number_of_nodes
10+
from openaerostruct.mphys.utils import get_number_of_nodes, get_node_indices
1011
from openaerostruct.mphys.aero_mesh import AeroMesh
1112
from openaerostruct.mphys.demux_surface_mesh import DemuxSurfaceMesh
1213
from openaerostruct.mphys.mux_surface_forces import MuxSurfaceForces
@@ -146,3 +147,36 @@ def get_number_of_nodes(self):
146147
if self.comm.rank == 0:
147148
return self.nnodes
148149
return 0
150+
151+
def get_tagged_indices(self, tags):
152+
"""
153+
Method that returns grid IDs for a list of body/boundary tags.
154+
155+
Parameters
156+
----------
157+
tags : list[str]
158+
list of surface names from which to pull the gridIDs
159+
160+
Returns
161+
-------
162+
grid_ids : list[int]
163+
list of grid IDs that correspond to given body/boundary tags
164+
"""
165+
if self.comm.rank == 0:
166+
if tags == -1 or tags == [-1]:
167+
return list(range(self.nnodes))
168+
else:
169+
all_surf_indices = get_node_indices(self.surfaces)
170+
tagged_indices = []
171+
for tag in tags:
172+
if tag in all_surf_indices:
173+
surf_indices = all_surf_indices[tag].flatten()
174+
tagged_indices.extend(list(surf_indices))
175+
else:
176+
warnings.warn(
177+
f'Tag name "{tag}" not found in list of added surfaces. Skipping tag.',
178+
category=RuntimeWarning,
179+
stacklevel=2,
180+
)
181+
return tagged_indices
182+
return []
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
import importlib
3+
import numpy as np
4+
5+
from openaerostruct.mphys import AeroBuilder
6+
from openaerostruct.utils.testing import get_default_surfaces
7+
8+
# check if mphys/mpi4py is available
9+
try:
10+
from mpi4py import MPI
11+
12+
mpi_flag = True
13+
except ImportError:
14+
mpi_flag = False
15+
16+
mphys_flag = importlib.util.find_spec("mphys") is not None
17+
18+
19+
@unittest.skipUnless(mphys_flag and mpi_flag, "mphys/mpi4py is required.")
20+
class Test(unittest.TestCase):
21+
def setUp(self):
22+
self.surfaces = get_default_surfaces()
23+
comm = MPI.COMM_WORLD
24+
# Create mphys builder for aero solver
25+
self.aero_builder = AeroBuilder(self.surfaces)
26+
self.aero_builder.initialize(comm)
27+
28+
def test_tagged_indices(self):
29+
wing_nnodes = self.surfaces[0]["mesh"].size // 3
30+
tail_nnodes = self.surfaces[1]["mesh"].size // 3
31+
with self.subTest(case="wing"):
32+
wing_inds = self.aero_builder.get_tagged_indices(["wing"])
33+
np.testing.assert_equal(wing_inds, np.arange(0, wing_nnodes))
34+
35+
with self.subTest(case="tail"):
36+
tail_inds = self.aero_builder.get_tagged_indices(["tail"])
37+
np.testing.assert_equal(tail_inds, np.arange(wing_nnodes, wing_nnodes + tail_nnodes))
38+
39+
with self.subTest(case="wing+tail"):
40+
wt_inds = self.aero_builder.get_tagged_indices(["wing", "tail"])
41+
np.testing.assert_equal(wt_inds, np.arange(0, wing_nnodes + tail_nnodes))
42+
43+
with self.subTest(case="all"):
44+
wt_inds = self.aero_builder.get_tagged_indices(-1)
45+
np.testing.assert_equal(wt_inds, np.arange(0, wing_nnodes + tail_nnodes))
46+
47+
48+
if __name__ == "__main__":
49+
unittest.main()

openaerostruct/mphys/utils.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,39 @@ def get_src_indices(surfaces):
3838
3939
"""
4040
src_indices = {}
41-
nnodes = 0
41+
nindices = 0
4242
for surface in surfaces:
4343
surf_name = surface["name"]
4444
mesh = surface["mesh"]
4545
nx, ny, _ = mesh.shape
46-
surf_indices = np.arange(mesh.size) + nnodes
46+
surf_indices = np.arange(mesh.size) + nindices
4747
src_indices[surf_name] = surf_indices.reshape(nx, ny, 3)
48-
nnodes += mesh.size
48+
nindices += mesh.size
4949
return src_indices
50+
51+
52+
def get_node_indices(surfaces):
53+
"""
54+
Get node indices for each surface that define the ordering of each node for all surfaces.
55+
56+
Parameters
57+
----------
58+
surfaces : list[dict]
59+
List of all surfaces.
60+
61+
Returns
62+
-------
63+
node_indices : dict
64+
Dictionary holding node indices sorted by surface name.
65+
66+
"""
67+
node_indices = {}
68+
nnodes = 0
69+
for surface in surfaces:
70+
surf_name = surface["name"]
71+
mesh = surface["mesh"]
72+
nx, ny, _ = mesh.shape
73+
surf_indices = np.arange(nx * ny) + nnodes
74+
node_indices[surf_name] = surf_indices.reshape(nx, ny)
75+
nnodes += nx * ny
76+
return node_indices

0 commit comments

Comments
 (0)