TacsBuilder class¶
TACS MPhys interface centers around the TacsBuilder
class.
The TacsBuilder
is responsible for creating Scenarios,
an OpenMDAO group that contains an analysis condition in a multipoint optimization.
API Reference¶
- class tacs.mphys.builder.TacsBuilder(*args: Any, **kwargs: Any)[source]¶
Create the Builder responsible for creating MPhys Scenario's based on TACS Analyses.
- Parameters:
mesh_file (str or pyNastran.bdf.bdf.BDF) -- The BDF file or a pyNastran BDF object to load.
assembler_setup (collections.abc.Callable, optional) --
User-defined callback function for modifying pyTACS assembler prior to initialization. This is used for adding point mass DVs to the model. Defaults to None. follows:
def assembler_setup(fea_assembler):
fea_assembler is the uninitialized pyTACS assembler instance created by the builder.
element_callback (collections.abc.Callable, optional) --
User-defined callback function for setting up TACS elements and element DVs. Defaults to None. See Initializing with elemCallBack for more info. The calling sequence for elem_callback must be as follows:
def elem_callback(dv_num, comp_id, comp_descript, elem_descripts, special_dvs, **kwargs):
The dv_num is the current counter which must be used by the user when creating a constitutive object with design variables.
comp_id is the ID number used by tacs to reference this property group. Use kwargs['propID'] to get the corresponding Nastran property ID that is read in from the BDF.
comp_descript is the component description label read in from optional formatted comments in BDF file
elem_descripts are the name of the elements belonging to this group (e.g. CQUAD4, CTRIA3, CTETRA, etc). This value will be a list since one component may contain multiple compatible element types. Example: ['CQUAD4', CTRIA3']
global_dvs is a dictionary containing information about any global DVs that have been added. elem_callback must return a list containing as many TACS element objects as there are element types in elemDescripts (one for each).
problem_setup (collections.abc.Callable, optional) --
This function is called each time a new MPhys Scenario is created. This function sets up the problem by adding fixed loads, modifying options, and adding eval functions. The function should have the following structure:
def problem_setup(scenario_name, fea_assembler, problem):
scenario_name is a str denoting which MPhys Scenario the problem is currently being set up for. fea_assembler is the uninitialized pyTACS assembler instance created by the builder. problem is the tacs.BaseProblem class being setup for this scenario.
constraint_setup (collections.abc.Callable, optional) --
This function is called each time a new MPhys Scenario is created. This function sets up a series of constraints to be run after at the end of an MPhys analysis. The function should have the following structure:
def constraint_setup(scenario_name, fea_assembler, constraints):
buckling_setup (collections.abc.Callable, optional) --
This function is called each time a new MPhys Scenario is created. This function sets up a buckling problem to be run after at the end of an MPhys analysis. The function should have the following structure:
def buckling_setup(scenario_name, fea_assembler)
pytacs_options (dict, optional) -- Options dictionary passed to pyTACS assembler.
check_partials (bool, optional) -- This flag allows TACS components partial derivative routines to be evaluated in forward mode without raising an error. This lets OpenMDAO's check_partials routine run without errors, allowing users to check TACS' reverse derivatives. The forward derivative checks will still not be meaningful since TACS only supports reverse mode. Defaults to False.
conduction (bool, optional) -- Flag to determine weather TACS component represents a thermal (True) or structural (False) analysis. Defaults to False.
coupled (bool, optional) -- Flag to determine of if multidisciplinary coupling variables should be turned on (used in aerostructural/thermostructural analyses). Defaults to True.
write_solution (bool, optional) -- Flag to determine whether to write out TACS solutions to f5 file each design iteration. Defaults to True.
separate_mass_dvs (bool, optional) -- Flag to determine if TACS' mass dvs should be lumped into the struct_dv input vector (False) or split into separate OpenMDAO inputs based on their assigned names (True). Defaults to False.
res_ref (float, optional) -- Reference residual norm to be used by OpenMDAO's residual scaling. Can be useful for ensuring residuals from different coupled disciplines are of a similar order of magnitude. Defaults to None.
Examples
- assembler_setup:
>>> def assembler_setup(fea_assembler): >>> # Assign dvs for point mass elements 10401 and 10402 >>> # to vary mass values during optimization >>> fea_assembler.assignMassDV("engine_mass", 10401) >>> fea_assembler.assignMassDV("fuel_mass", 10402)
- element_callback:
>>> def elem_callback(dv_num, comp_id, comp_descript, elem_descripts, special_dvs, **kwargs): >>> # Material properties >>> rho = 2500.0 # density kg/m^3 >>> E = 70e9 # Young's modulus (Pa) >>> nu = 0.3 # Poisson's ratio >>> ys = 464.0e6 # yield stress >>> >>> # Plate geometry >>> tplate = 0.005 # 5 mm >>> >>> # Set up material properties >>> prop = constitutive.MaterialProperties(rho=rho, E=E, nu=nu, ys=ys) >>> # Set up constitutive model >>> con = constitutive.IsoShellConstitutive(prop, t=tplate, tNum=dv_num) >>> # Set the transform used to define shell stresses, None defaults to NaturalShellTransform >>> transform = None >>> # Set up tacs element for every entry in elem_descripts >>> # According to the bdf file, elem_descripts should always be ["CQUAD4"] >>> elem_list = [] >>> for descript in elem_descripts: >>> if descript == 'CQUAD4': >>> elem = elements.Quad4Shell(transform, con) >>> else: # Add a catch for any unexpected element types >>> raise ValueError(f"Unexpected element of type {descript}.") >>> return elem_list
- problem_setup:
>>> def problem_setup(scenario_name, fea_assembler, problem): >>> # Set scenario to its own output directory >>> problem.setOption('outputDir', scenario_name) >>> >>> # Only include mass from elements that belong to pytacs components (i.e. skip concentrated masses) >>> comp_ids = fea_assembler.selectCompIDs(nGroup=-1) >>> problem.addFunction('struct_mass', functions.StructuralMass, comp_ids=comp_ids) >>> problem.addFunction('ks_vmfailure', functions.KSFailure, >>> safetyFactor=1.5, ksWeight=100.0) >>> >>> # load factor >>> if scenario_name == "maneuver_2_5g": >>> n = 2.5 >>> elif scenario_name == "maneuver_m1g": >>> n = -1.0 >>> else: >>> n = 1.0 >>> # Add gravity load >>> g = n * np.array([0.0, 0.0, -9.81]) # m/s^2 >>> problem.addInertialLoad(g)
- constraint_setup:
>>> def constraint_setup(scenario_name, fea_assembler, constraints): >>> # Add constraint on enclosed volume of structure >>> constr = fea_assembler.createVolumeConstraint("constraints") >>> constr.addConstraint("volume") >>> constraints.append(constr)
- buckling_setup:
>>> def buckling_setup(scenario_name, fea_assembler): >>> # Add buckling analysis only to 2.5g maneuver scenario >>> if scenario_name == "maneuver_2_5g": >>> problem = fea_assembler.createBucklingProblem( >>> "buckling", sigma=1.0, numEigs=2 >>> ) >>> problem.setOption("L2Convergence", 1e-20) >>> problem.setOption("L2ConvergenceRel", 1e-20) >>> return problem
- initialize(comm)[source]¶
Initialize pyTACS. This method will be called when the MPI comm is available
- Parameters:
comm (
Comm
) -- The communicator object created for this xfer object instance.
- get_coupling_group_subsystem(scenario_name=None)[source]¶
The subsystem that this builder will add to the CouplingGroup
- Parameters:
scenario_name (str, optional) -- The name of the scenario calling the builder.
- Returns:
subsystem -- The openmdao subsystem that handles all the computations for this solver. Transfer schemes can return multiple subsystems
- Return type:
openmdao.api.Group
- get_mesh_coordinate_subsystem(scenario_name=None)[source]¶
The subsystem that contains the subsystem that will return the mesh coordinates
- Parameters:
scenario_name (str, optional) -- The name of the scenario calling the builder.
- Returns:
mesh -- The openmdao subsystem that has an output of coordinates.
- Return type:
Component
orGroup
- get_pre_coupling_subsystem(scenario_name=None)[source]¶
Method that returns the openmdao subsystem to be added to each scenario before the coupling group
- Parameters:
scenario_name (str, optional) -- The name of the scenario calling the builder.
- Returns:
subsystem
- Return type:
openmdao.api.Group
- get_post_coupling_subsystem(scenario_name=None)[source]¶
Method that returns the openmdao subsystem to be added to each scenario after the coupling group
- Parameters:
scenario_name (str, optional) -- The name of the scenario calling the builder.
- Returns:
subsystem
- Return type:
openmdao.api.Group
- get_ndof()[source]¶
The number of degrees of freedom used at each output location.
- Returns:
ndof -- number of degrees of freedom of each node in the domain
- Return type:
- get_number_of_nodes()[source]¶
Get the number of nodes on this processor, not including lagrange multiplier nodes
- get_dv_bounds()[source]¶
Get arrays containing the lower and upper bounds for the design variables, in the form needed by OpenMDAO's add_design_variable method.
- Returns:
lower and upper bounds for the design variables
- Return type:
list of ndarray