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 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]