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.

  • coupling_loads (list[str] or str or None, optional) -- List of coupling loads to add to right handside of FEA state equation. These loads correspond to the nodal forces on the model. Multiple load sources can be specified, these will be added together before being applied to the model. This is used in aerostructural/thermostructural analyses. Defaults to None.

  • 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 or Group

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:

int

get_number_of_nodes()[source]

Get the number of nodes on this processor, not including lagrange multiplier nodes

get_initial_dvs()[source]

Get an array holding all dvs values that have been added to TACS

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

get_dv_scalers()[source]

Get an array containing the scaling factors for the design variables, in the form needed by OpenMDAO's add_design_variable method.

Returns:

Scaling values

Return type:

array

get_ndv()[source]

Get total number of structural design variables across all procs

get_solver()[source]
get_fea_assembler()[source]

Returns underlying pytacs object.

get_tagged_indices(tags)[source]

Method that returns grid IDs for a list of body/boundary tags.

Parameters:

tags (list[str, int]) -- list of component names or node IDs to include in body

Returns:

grid_ids -- list of grid IDs that correspond to given body/boundary tags

Return type:

list[int]