Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding get_tagged_indices to mphys wrapper #414

Merged
merged 12 commits into from
Jul 28, 2023
3 changes: 3 additions & 0 deletions .github/workflows/oas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
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
VSP_VERSION: ['3.27.1'] # used for both builds
PETSC_VERSION_LATEST: ['3.19.1']
CYTHON_VERSION: ['0.29.36'] # used for both builds

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -117,6 +118,8 @@ jobs:
export PETSC_DIR=`pwd`
./configure --PETSC_ARCH=$PETSC_ARCH --download-fblaslapack
make PETSC_DIR=$PETSC_DIR PETSC_ARCH=$PETSC_ARCH all
# Cython 3.0.0 break petsc4py install
pip install cython==${{ matrix.CYTHON_VERSION }}
pip install petsc4py==${{ matrix.PETSC_VERSION_LATEST }}

# We need pySpline/pyGeo to run FFD tests.
Expand Down
36 changes: 35 additions & 1 deletion openaerostruct/mphys/aero_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"""

import copy
import warnings

import openmdao.api as om

from openaerostruct.mphys.utils import get_number_of_nodes
from openaerostruct.mphys.utils import get_number_of_nodes, get_node_indices
from openaerostruct.mphys.aero_mesh import AeroMesh
from openaerostruct.mphys.demux_surface_mesh import DemuxSurfaceMesh
from openaerostruct.mphys.mux_surface_forces import MuxSurfaceForces
Expand Down Expand Up @@ -146,3 +147,36 @@ def get_number_of_nodes(self):
if self.comm.rank == 0:
return self.nnodes
return 0

def get_tagged_indices(self, tags):
"""
Method that returns grid IDs for a list of body/boundary tags.

Parameters
----------
tags : list[str]
list of surface names from which to pull the gridIDs

Returns
-------
grid_ids : list[int]
list of grid IDs that correspond to given body/boundary tags
"""
if self.comm.rank == 0:
if tags == -1 or tags == [-1]:
return list(range(self.nnodes))
else:
all_surf_indices = get_node_indices(self.surfaces)
tagged_indices = []
for tag in tags:
if tag in all_surf_indices:
surf_indices = all_surf_indices[tag].flatten()
tagged_indices.extend(list(surf_indices))
else:
warnings.warn(
f'Tag name "{tag}" not found in list of added surfaces. Skipping tag.',
category=RuntimeWarning,
stacklevel=2,
)
return tagged_indices
return []
49 changes: 49 additions & 0 deletions openaerostruct/mphys/tests/test_aero_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest
import importlib
import numpy as np

from openaerostruct.mphys import AeroBuilder
from openaerostruct.utils.testing import get_default_surfaces

# check if mphys/mpi4py is available
try:
from mpi4py import MPI

mpi_flag = True
except ImportError:
mpi_flag = False

mphys_flag = importlib.util.find_spec("mphys") is not None


@unittest.skipUnless(mphys_flag and mpi_flag, "mphys/mpi4py is required.")
class Test(unittest.TestCase):
def setUp(self):
self.surfaces = get_default_surfaces()
comm = MPI.COMM_WORLD
# Create mphys builder for aero solver
self.aero_builder = AeroBuilder(self.surfaces)
self.aero_builder.initialize(comm)

def test_tagged_indices(self):
wing_nnodes = self.surfaces[0]["mesh"].size // 3
tail_nnodes = self.surfaces[1]["mesh"].size // 3
with self.subTest(case="wing"):
wing_inds = self.aero_builder.get_tagged_indices(["wing"])
np.testing.assert_equal(wing_inds, np.arange(0, wing_nnodes))

with self.subTest(case="tail"):
tail_inds = self.aero_builder.get_tagged_indices(["tail"])
np.testing.assert_equal(tail_inds, np.arange(wing_nnodes, wing_nnodes + tail_nnodes))

with self.subTest(case="wing+tail"):
wt_inds = self.aero_builder.get_tagged_indices(["wing", "tail"])
np.testing.assert_equal(wt_inds, np.arange(0, wing_nnodes + tail_nnodes))

with self.subTest(case="all"):
wt_inds = self.aero_builder.get_tagged_indices(-1)
np.testing.assert_equal(wt_inds, np.arange(0, wing_nnodes + tail_nnodes))


if __name__ == "__main__":
unittest.main()
33 changes: 30 additions & 3 deletions openaerostruct/mphys/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,39 @@ def get_src_indices(surfaces):

"""
src_indices = {}
nnodes = 0
nindices = 0
for surface in surfaces:
surf_name = surface["name"]
mesh = surface["mesh"]
nx, ny, _ = mesh.shape
surf_indices = np.arange(mesh.size) + nnodes
surf_indices = np.arange(mesh.size) + nindices
src_indices[surf_name] = surf_indices.reshape(nx, ny, 3)
nnodes += mesh.size
nindices += mesh.size
return src_indices


def get_node_indices(surfaces):
"""
Get node indices for each surface that define the ordering of each node for all surfaces.

Parameters
----------
surfaces : list[dict]
List of all surfaces.

Returns
-------
node_indices : dict
Dictionary holding node indices sorted by surface name.

"""
node_indices = {}
nnodes = 0
for surface in surfaces:
surf_name = surface["name"]
mesh = surface["mesh"]
nx, ny, _ = mesh.shape
surf_indices = np.arange(nx * ny) + nnodes
node_indices[surf_name] = surf_indices.reshape(nx, ny)
nnodes += nx * ny
return node_indices