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

Add dictionary input for setting aflr4AIM options. #236

Merged
merged 5 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions tacs/caps2tacs/aflr_aim.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
class AflrAim:
def __init__(self, caps_problem, comm, root=0):
"""
MPI wrapper class for AflrAIM from ESP/CAPS
Requires use of ESPbeta at the moment
MPI wrapper class for AflrAIM from ESP/CAPS.
"""

self.caps_problem = caps_problem
Expand All @@ -15,6 +14,8 @@ def __init__(self, caps_problem, comm, root=0):
# holds aflr4 aim
self._aim = None

self._dictOptions = None

self._build_aim()
return

Expand All @@ -40,18 +41,55 @@ def _build_aim(self):
self._aim = self.caps_problem.analysis.create(aim="aflr4AIM", name="aflr4")
return

def set_mesh(
self, ff_growth=1.4, min_scale=0.05, max_scale=0.5, use_quad=False, no_prox=True
):
# set surface mesh properties
def set_mesh(self, min_scale=0.05, max_scale=0.5, AFLR4_Quad=False, no_prox=True):
"""
Set mesh properties for AFLR4 AIM. A few options are available in this routine.
To set other options for AFLR4, use the save_dict_options routine.

Parameters
----------
min_scale: Relative scale of minimum spacing to reference length.
The relative scale of minimum spacing to reference length (ref_len) controls
the minimum spacing that can be set on any component/body surface.
max_scale: Relative scale of maximum spacing to reference length.
The relative scale of maximum spacing to reference length (ref_len) controls
the maximum spacing that can be set on any component/body surface.
AFLR4_Quad: Generate a mixed quad/tria-face grid.
no_prox: Disable proximity checking.
Proximity checking is automatically disabled if there is only one component/body defined.
"""

if self.root_proc:
self.aim.input.ff_cdfr = ff_growth
self.aim.input.min_scale = min_scale
self.aim.input.max_scale = max_scale
self.aim.input.AFLR4_Quad = use_quad
self.aim.input.AFLR4_Quad = AFLR4_Quad
self._aim.input.no_prox = no_prox
return self

def save_dict_options(self, dictOptions: dict = None):
"""
Optional method to set AFLR4 mesh settings using dictionaries.
Call this before setting up the TACS model. The dictionary should take
the form of, e.g.:

dictOptions['aflr4AIM']['myOption'] = myValue
"""
self._dictOptions = dictOptions

return self

def _set_dict_options(self):
"""
Set AFLR4 options via dictionaries.
"""
dictOptions = self._dictOptions

if self.root_proc:
for ind, option in enumerate(dictOptions["aflr4AIM"]):
self.aim.input[option].value = dictOptions["aflr4AIM"][option]

return self

def register_to(self, tacs_aim):
"""
cascade method to register the egads aim to the tacs aim wrapper class
Expand Down
27 changes: 27 additions & 0 deletions tacs/caps2tacs/egads_aim.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class EgadsAim:

def __init__(self, caps_problem, comm):
self.comm = comm

self._dictOptions = None

if comm is None or comm.rank == 0:
self._aim = caps_problem.analysis.create(aim="egadsTessAIM")
self._is_setup = False
Expand Down Expand Up @@ -43,6 +46,30 @@ def set_mesh(
self._is_setup = True
return self

def save_dict_options(self, dictOptions: dict = None):
"""
Optional method to set EGADS mesh settings using dictionaries.
Call this before setting up the TACS model. The dictionary should take
the form of, e.g.:

dictOptions['egadsTessAIM']['myOption'] = myValue
"""
self._dictOptions = dictOptions

return self

def _set_dict_options(self):
"""
Set EGADS options via dictionaries.
"""
dictOptions = self._dictOptions

if self.root_proc:
for ind, option in enumerate(dictOptions["egadsTessAIM"]):
self.aim.input[option].value = dictOptions["egadsTessAIM"][option]

return self

@property
def is_setup(self) -> bool:
return self._is_setup
Expand Down
30 changes: 30 additions & 0 deletions tacs/caps2tacs/tacs_aim.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ def __init__(self, caps_problem, comm=None):
self._design_variables = []
self._mesh_aim = None

self._dict_options = None

# build flags
self._setup = False
self._first_setup = True
Expand Down Expand Up @@ -179,6 +181,9 @@ def setup_aim(
dv.name: dv.DV_dictionary for dv in self._design_variables
}

if self._dict_options is not None:
self._set_dict_options()

# end of serial or root proc section

# note that setup is finished now
Expand Down Expand Up @@ -302,6 +307,31 @@ def update_properties(self):

return

def save_dict_options(self, aimOptions: dict = None):
"""
Optional method to set tacsAIM settings using dictionaries. Settings specified
through dictionaries take precedence over other methods. The dictionary should
take the form of, e.g.:

aimOptions['tacsAIM']['myOption'] = myValue
"""

self._dict_options = aimOptions

return self

@root_proc
def _set_dict_options(self):
"""
Set any options that were specified through dictionaries.
"""
aimOptions = self._dict_options

for ind, option in enumerate(aimOptions["tacsAim"]):
self.aim.input[option].value = aimOptions["tacsAim"][option]

return self

@root_proc
def pre_analysis(self):
"""
Expand Down
10 changes: 7 additions & 3 deletions tacs/caps2tacs/tacs_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def tacs_aim(self) -> TacsAim:
return self._tacs_aim

@property
def mesh_aim(self):
def mesh_aim(self) -> AflrAim:
return self._mesh_aim

@property
Expand All @@ -45,7 +45,7 @@ def uses_aflr(self):
return isinstance(self.mesh_aim, AflrAim)

@classmethod
def build(cls, csm_file, comm=None, mesh="egads", problem_name: str = "capsStruct"):
def build(cls, csm_file, comm=None, mesh="egads", problem_name: str = "capsStruct", verbosity=1):
"""
make a pyCAPS problem with the tacsAIM and egadsAIM on serial / root proc

Expand All @@ -61,7 +61,7 @@ def build(cls, csm_file, comm=None, mesh="egads", problem_name: str = "capsStruc
assert mesh in cls.MESH_AIMS
if comm is None or comm.rank == 0:
caps_problem = pyCAPS.Problem(
problemName=problem_name, capsFile=csm_file, outLevel=1
problemName=problem_name, capsFile=csm_file, outLevel=verbosity
)
tacs_aim = TacsAim(caps_problem, comm)
mesh_aim = None
Expand Down Expand Up @@ -117,6 +117,10 @@ def setup(self, include_aim: bool = True):
if include_aim:
self.tacs_aim.setup_aim()

# Set additional options for meshing AIM through dictionaries
if self.mesh_aim._dictOptions is not None:
self.mesh_aim._set_dict_options()

# go ahead and generate the first input files and mesh for TACS
if not self.tacs_aim.change_shape:
self.tacs_aim.pre_analysis()
Expand Down