mesh_utils Package

bdf_equivalence Module

defines:
model = bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol,

renumber_nodes=False, neq_max=4, xref=True, node_set=None, size=8, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, log=None, debug=True)

pyNastran.bdf.mesh_utils.bdf_equivalence._bdf_equivalence_nodes(bdf_filename: str, tol: float, renumber_nodes: bool = False, neq_max: int = 4, xref: bool = True, node_set: Optional[List[NDArrayNint]] = None, log: Optional[SimpleLogger] = None, debug: bool = True, method: str = 'new', idtype: str = 'int32', fdtype: str = 'float64') → Tuple[BDF, List[Tuple[int, int]]][source]

helper for bdf_equivalence_nodes

pyNastran.bdf.mesh_utils.bdf_equivalence._check_for_referenced_nodes(model: pyNastran.bdf.bdf.BDF, node_set: Optional[Any], nids: Any, all_nids: Any, nodes_xyz: Any) → Optional[Any][source]

helper function for _eq_nodes_setup

pyNastran.bdf.mesh_utils.bdf_equivalence._eq_nodes_build_tree_new(kdt: scipy.spatial.cKDTree, nodes_xyz: NDArrayN3float, nids: NDArrayNint, all_node_set: NDArrayNint, nnodes: int, is_not_node_set: bool, tol: float, log: SimpleLogger, inew=None, node_set=None, neq_max: int = 4, msg: str = '', debug: float = False) → Tuple[Any, List[Tuple[int, int]]][source]
pyNastran.bdf.mesh_utils.bdf_equivalence._eq_nodes_final(nid_pairs, model: pyNastran.bdf.bdf.BDF, tol: float, all_node_set: Any, debug: bool = False) → None[source]

apply nodal equivalencing to model

pyNastran.bdf.mesh_utils.bdf_equivalence._eq_nodes_setup_node(model: pyNastran.bdf.bdf.BDF, renumber_nodes: bool = False, idtype: str = 'int32') → Tuple[Any, Any][source]

helper function for _eq_nodes_setup that doesn’t handle node sets

pyNastran.bdf.mesh_utils.bdf_equivalence._eq_nodes_setup_node_set(model: pyNastran.bdf.bdf.BDF, node_set: List[Any], all_node_set: Any, renumber_nodes: bool = False, idtype: str = 'int32') → Tuple[Any, Any][source]

helper function for _eq_nodes_setup that handles node_sets

pyNastran.bdf.mesh_utils.bdf_equivalence._get_tree(nodes_xyz: Any, msg: str = '') → scipy.spatial.ckdtree.cKDTree[source]

gets the kdtree

pyNastran.bdf.mesh_utils.bdf_equivalence._get_xyz_cid0(model: pyNastran.bdf.bdf.BDF, nids: Any, fdtype: str = 'float32') → Any[source]

gets xyz_cid0

pyNastran.bdf.mesh_utils.bdf_equivalence._nodes_xyz_nids_to_nid_pairs(nodes_xyz: NDArrayN3float, nids: NDArrayNint, all_node_set: NDArrayNint, tol: float, log: SimpleLogger, inew: NDArrayNint, node_set: Optional[NDArrayNint] = None, neq_max: int = 4, method: str = 'new', debug: bool = False) → List[Tuple[int, int]][source]

Helper for equivalencing

Returns
nid_pairsList[Tuple[int, int]]

a series of (nid1, nid2) pairs

pyNastran.bdf.mesh_utils.bdf_equivalence._nodes_xyz_nids_to_nid_pairs_new(kdt: scipy.spatial.ckdtree.cKDTree, nids: Any, all_node_set: Any, node_set: Optional[Any], tol: float)[source]

helper function for bdf_equivalence_nodes

pyNastran.bdf.mesh_utils.bdf_equivalence._simplify_node_set(node_set: Union[List[int], Set[int], List[Any], None], idtype: str = 'int32') → Optional[List[Any]][source]
accepts multiple forms of the node_set parameter
  • list[int]

  • set[int]

  • list[int ndarray]

  • int ndarray

pyNastran.bdf.mesh_utils.bdf_equivalence._update_grid(node1: GRID, node2: GRID)[source]

helper method for _eq_nodes_final

pyNastran.bdf.mesh_utils.bdf_equivalence.bdf_equivalence_nodes(bdf_filename: str, bdf_filename_out: str, tol: float, renumber_nodes: bool = False, neq_max: int = 4, xref: bool = True, node_set: Optional[Union[List[int], NDArrayNint]] = None, size: int = 8, is_double: bool = False, remove_collapsed_elements: bool = False, avoid_collapsed_elements: bool = False, crash_on_collapse: bool = False, log: Optional[SimpleLogger] = None, debug: bool = True, method: str = 'new') → BDF[source]

Equivalences nodes; keeps the lower node id; creates two nodes with the same

Parameters
bdf_filenamestr / BDF

str : bdf file path BDF : a BDF model that is fully valid (see xref)

bdf_filename_outstr

a bdf_filename to write

tolfloat

the spherical tolerance

renumber_nodesbool

should the nodes be renumbered (default=False)

neq_maxint

the number of “close” points (default=4)

xrefbool

does the model need to be cross_referenced (default=True; only applies to model option)

node_setList[int] / (n, ) ndarray; default=None

the list/array of nodes to consider (not supported with renumber_nodes=True)

sizeint; {8, 16}; default=8

the bdf write precision

is_doublebool; default=False

the field precision to write

remove_collapsed_elementsbool; default=False (unsupported)
True1D/2D/3D elements will not be collapsed;

CELASx/CDAMP/MPC/etc. are not considered

False : no elements will be removed

avoid_collapsed_elementsbool; default=False (unsupported)
Trueonly collapses that don’t break 1D/2D/3D elements will be considered;

CELASx/CDAMP/MPC/etc. are considered

False : element can be collapsed

crash_on_collapsebool; default=False
stop if nodes have been collapsed

False: blindly move on True: rereads the BDF which catches doubled nodes (temporary);

in the future collapse=True won’t need to double read; an alternative is to do Patran’s method of avoiding collapse)

debugbool

bdf debugging

method: str; default=’new’

‘new’: doesn’t require neq_max; new in v1.3 ‘old’: use neq_max; used in v1.2

loglogger(); default=None

bdf logging

Returns
modelBDF()

The BDF model corresponding to bdf_filename_out

Warning

I doubt SPOINTs/EPOINTs work correctly ..

Warning

xref not fully implemented (assumes cid=0) ..

Todo

node_set still does work on the all the nodes in the big kdtree loop, which is very inefficient

Todo

remove_collapsed_elements is not supported ..

Todo

avoid_collapsed_elements is not supported ..

pyNastran.bdf.mesh_utils.bdf_equivalence.get_all_node_set(node_set: Optional[List[Any]]) → Any[source]

bdf_merge Module

defines:
  • bdf_merge(bdf_filenames, bdf_filename_out=None, renumber=True, encoding=None, size=8,

    is_double=False, cards_to_skip=None, log=None, skip_case_control_deck=False)

pyNastran.bdf.mesh_utils.bdf_merge._apply_scalar_cards(model: pyNastran.bdf.bdf.BDF, model2_renumber: pyNastran.bdf.bdf.BDF) → None[source]

apply cards from model2 to model if they don’t exist in model

pyNastran.bdf.mesh_utils.bdf_merge._assemble_mapper(mappers: List[MAPPER], mapper_0: MAPPER, data_members: List[str], mapper_renumber: Optional[MAPPER] = None) → None[source]

Assemble final mappings from all original ids to the ids in the merged and possibly renumbered model.

Parameters
mappersList[mapper]
mapperdict[key]value
key???

???

value???

???

mapper_0mapper
key???

???

value???

???

data_membersList[str]
list of things to include in the mappers?
data_members = [

‘coords’, ‘nodes’, ‘elements’, ‘masses’, ‘properties’, ‘properties_mass’, ‘materials’, ‘sets’, ‘rigid_elements’, ‘mpcs’,

]

mapper_renumberdict[key]: value; default=None
keystr

a BDF attribute

valuedict[id_old]id_new

a sub dictionary that is used to map the node/element/etc. ids

mapper = {

‘elements’ : eid_map, ‘nodes’ : nid_map, ‘coords’ : cid_map, …

}

Returns
mappers_allList[mappers]

One mapper for each bdf_filename

pyNastran.bdf.mesh_utils.bdf_merge._dict_key_to_key(dictionary) → Dict[int, int][source]

creates a dummy map from the nominal key to the nominal key

pyNastran.bdf.mesh_utils.bdf_merge._dicts_key_to_key(dictionaries: List[Dict[int, Any]]) → Dict[int, int][source]

Creates a dummy map from the nominal key to the nominal key for multiple input dictionaries. This is intended for use with:

  • SPCs, MPCs, Loads

pyNastran.bdf.mesh_utils.bdf_merge._get_mapper_0(model: BDF) → MAPPER[source]

Get the mapper for the first model.

Parameters
modelBDF()

the bdf model object

Returns
mapperdict[key]: value
keystr

a BDF attribute

valuedict[id_old]id_new

a sub dictionary that is used to map the node/element/etc. ids

mapper = {

‘elements’ : eid_map, ‘nodes’ : nid_map, ‘coords’ : cid_map, …

}

pyNastran.bdf.mesh_utils.bdf_merge._renumber_mapper(mapper_0: MAPPER, mapper_renumber: MAPPER)[source]

Renumbers a mapper

Parameters
mapper_0dict[key]: value
keystr

a BDF attribute

valuedict[id_old]id_new

a sub dictionary that is used to map the node/element/etc. ids

mapper = {

‘elements’ : eid_map, ‘nodes’ : nid_map, ‘coords’ : cid_map, …

}

mapper_renumber???

???

Returns
mapperdict[map_type]
map_type???

???

sub_mapperdict[key]value
key???

???

value???

???

pyNastran.bdf.mesh_utils.bdf_merge.bdf_merge(bdf_filenames: List[str], bdf_filename_out: Optional[str] = None, renumber: bool = True, encoding: Optional[str] = None, size: int = 8, is_double: bool = False, cards_to_skip: Optional[List[str]] = None, skip_case_control_deck: bool = False, log: Optional[SimpleLogger] = None) → Tuple[BDF, List[MAPPER]][source]

Merges multiple BDF into one file

Parameters
bdf_filenamesList[str]

list of bdf filenames

bdf_filename_outstr / None

the output bdf filename (default=None; None -> no writing)

renumberbool

should the bdf be renumbered (default=True)

encodingstr

the unicode encoding (default=None; system default)

sizeint; {8, 16}; default=8

the bdf write precision

is_doublebool; default=False

the field precision to write

cards_to_skipList[str]; (default=None -> don’t skip any cards)

There are edge cases (e.g. FLUTTER analysis) where things can break due to uncross-referenced cards. You need to disable entire classes of cards in that case (e.g. all aero cards).

skip_case_control_deckbool, optional, default

If true, don’t consider the case control deck while merging.

Returns
modelBDF

Merged model.

mappers_allList[mapper]
mapperDict[bdf_attribute]old_id_to_new_id_dict

List of mapper dictionaries of original ids to merged

bdf_attributestr

a BDF attribute (e.g., ‘nodes’, ‘elements’)

old_id_to_new_id_dictdict[id_old]id_new

a sub dictionary that is used to map the node/element/etc. ids

mapper = {

‘elements’ : eid_map, ‘nodes’ : nid_map, ‘coords’ : cid_map, …

}

Supports

nodes: GRID coords: CORDx elements: CQUAD4, CTRIA3, CTETRA, CPENTA, CHEXA, CELASx, CBAR, CBEAM

CONM1, CONM2, CMASS

properties: PSHELL, PCOMP, PSOLID, PMASS materials: MAT1, MAT8

Todo

doesn’t support SPOINTs/EPOINTs ..

Warning

still very preliminary ..

bdf_renumber Module

defines:
bdf_renumber(bdf_filename, bdf_filename_out, size=8, is_double=False,

starting_id_dict=None, round_ids=False, cards_to_skip=None, log=None, debug=False)

superelement_renumber(bdf_filename, bdf_filename_out=None, size=8, is_double=False,

starting_id_dict=None, cards_to_skip=None, log=None, debug=False)

pyNastran.bdf.mesh_utils.bdf_renumber._create_mid_map(model, mid)[source]

builds the mid_map

pyNastran.bdf.mesh_utils.bdf_renumber._create_nid_maps(model, starting_id_dict, nid)[source]

builds the nid_maps

pyNastran.bdf.mesh_utils.bdf_renumber._get_bdf_model(bdf_filename, cards_to_skip=None, log=None, debug=False)[source]

helper method

pyNastran.bdf.mesh_utils.bdf_renumber._update_case_control(model, mapper)[source]

Updates the case control deck; helper method for bdf_renumber.

Parameters
modelBDF()

the BDF object

mapperdict[str] = List[int]

Defines the possible case control header values for each entry (e.g. LOAD)

pyNastran.bdf.mesh_utils.bdf_renumber._update_case_key(key, elemental_quantities, seti2, eid_map, nid_map)[source]

Updates a Case Control SET card. A set may have an elemental result or a nodal result.

pyNastran.bdf.mesh_utils.bdf_renumber._update_coords(model, starting_id_dict, cid, cid_map)[source]

updates the coords

pyNastran.bdf.mesh_utils.bdf_renumber._update_elements(model, starting_id_dict, eid, eid_map, mass_id_map, rigid_elements_map)[source]

updates the elements

pyNastran.bdf.mesh_utils.bdf_renumber._update_materials(unused_model, starting_id_dict, mid, mid_map, all_materials)[source]
pyNastran.bdf.mesh_utils.bdf_renumber._update_mpcs(model, starting_id_dict, mpc_id, mpc_map)[source]

updates the mpcs

pyNastran.bdf.mesh_utils.bdf_renumber._update_nodes(model, starting_id_dict, nid, nid_map)[source]

updates the nodes

pyNastran.bdf.mesh_utils.bdf_renumber._update_properties(model, starting_id_dict, pid, properties_map, properties_mass_map)[source]

updates the properties

pyNastran.bdf.mesh_utils.bdf_renumber._update_spcs(model, starting_id_dict, spc_id, spc_map)[source]

updates the spcs

pyNastran.bdf.mesh_utils.bdf_renumber._write_bdf(model, bdf_filename_out, size=8, is_double=False)[source]

helper method

pyNastran.bdf.mesh_utils.bdf_renumber.bdf_renumber(bdf_filename: Union[str, pyNastran.bdf.bdf.BDF, _io.StringIO], bdf_filename_out: str, size=8, is_double=False, starting_id_dict=None, round_ids: bool = False, cards_to_skip: Optional[List[str]] = None, log=None, debug=False) → pyNastran.bdf.bdf.BDF[source]

Renumbers a BDF

Parameters
bdf_filenamestr / BDF

str : a bdf_filename (string; supported) BDF : a BDF model that has been cross referenced and is fully valid (an equivalenced deck is not valid)

bdf_filename_outstr / None

str : a bdf_filename to write None : don’t write the BDF

sizeint; {8, 16}; default=8

the bdf write precision

is_doublebool; default=False

the field precision to write

starting_id_dictdict, None (default=None)

None : renumber everything starting from 1 dict : {key : starting_id}

keystr

the key (e.g. eid, nid, cid, …)

starting_idint, None

int : the value to start from None : don’t renumber this key

round_idsbool; default=False

Should a rounding up be applied for each variable? This makes it easier to read a deck and verify that it’s been renumbered properly. This only really applies when starting_id_dict is None

cards_to_skipList[str]; (default=None -> don’t skip any cards)

There are edge cases (e.g. FLUTTER analysis) where things can break due to uncross-referenced cards. You need to disable entire classes of cards in that case (e.g. all aero cards).

Returns
modelBDF()

a renumbered BDF object corresponding to bdf_filename_out

mapperDict[bdf_attribute]

List of mapper dictionaries of original ids to merged bdf_attribute : str

a BDF attribute (e.g., ‘nodes’, ‘elements’)

old_id_to_new_id_dictdict[id_old]id_new

a sub dictionary that is used to map the node/element/etc. ids

mapper = {

‘elements’ : eid_map, ‘nodes’ : nid_map, ‘coords’ : cid_map, …

}

Todo

bdf_model option for bdf_filename hasn’t been tested ..

Todo

add support for subsets (e.g. renumber only a subset of nodes/elements) ..

Todo

doesn’t support partial renumbering ..

Todo

doesn’t support element material coordinate systems ..

..warning :: spoints might be problematic…check
..warning :: still in development, but it usually brutally crashes

if it’s not supported

..warning :: be careful of card unsupported cards (e.g. ones not read in)
Supports
  • GRIDs - no superelements

  • COORDx

  • elements
    • CELASx/CONROD/CBAR/CBEAM/CQUAD4/CTRIA3/CTETRA/CPENTA/CHEXA

    • RBAR/RBAR1/RBE1/RBE2/RBE3/RSPLINE/RSSCON

  • properties
    • PSHELL/PCOMP/PCOMPG/PSOLID/PSHEAR/PBAR/PBARL PROD/PTUBE/PBEAM

  • mass
    • CMASSx/CONMx/PMASS

  • aero - FLFACT - SPLINEx - FLUTTER

  • partial case control - METHOD/CMETHOD/FREQENCY - LOAD/DLOAD/LSEQ/LOADSET…LOADSET/LSEQ is iffy - SET cards

    • nodes

    • elements

    • SPC/MPC/FLUTTER/FLFACT

  • constraints
    • SPC/SPCADD/SPCAX/SPCD

    • MPC/MPCADD

    • SUPORT/SUPORT1

  • solution control/methods
    • TSTEP/TSTEPNL

    • NLPARM

    • EIGB/EIGC/EIGRL/EIGR

  • sets
    • USET

  • other
    • tables

    • materials

    • loads/dloads

Not Done
  • SPOINT

  • any cards with SPOINTs - DMIG/DMI/DMIJ/DMIJI/DMIK/etc. - CELASx - CDAMPx

  • superelements

  • aero cards - CAEROx - PAEROx

  • thermal cards?

  • optimization cards

  • SETx

  • PARAM,GRDPNT,x; where x>0

  • GRID SEID

  • case control - STATSUB - SUBCASE - global SET cards won’t be renumbered properly

Examples

Renumber Everything; Start from 1

>>> bdf_renumber(bdf_filename, bdf_filename_out, size=8, is_double=False,
                 round_ids=False)

Renumber Everything; Start Material IDs from 100

>>> starting_id_dict = {
    'mid' : 100,
}
>>> bdf_renumber(bdf_filename, bdf_filename_out, size=8, is_double=False,
                 starting_ids_dict=starting_ids_dict, round_ids=False)

Only Renumber Material IDs

>>> starting_id_dict = {
    'cid' : None,
    'nid' : None,
    'eid' : None,
    'pid' : None,
    'mid' : 1,
    'spc_id' : None,
    'mpc_id' : None,
    'load_id' : None,
    'dload_id' : None,

‘method_id’ : None, ‘cmethod_id’ : None, ‘spline_id’ : None, ‘table_id’ : None, ‘flfact_id’ : None, ‘flutter_id’ : None, ‘freq_id’ : None, ‘tstep_id’ : None, ‘tstepnl_id’ : None, ‘suport_id’ : None, ‘suport1_id’ : None, ‘tf_id’ : None, ‘set_id’ : None,

} >>> bdf_renumber(bdf_filename, bdf_filename_out, size=8, is_double=False,

starting_ids_dict=starting_ids_dict, round_ids=False)

pyNastran.bdf.mesh_utils.bdf_renumber.get_renumber_starting_ids_from_model(model: pyNastran.bdf.bdf.BDF) → Dict[str, int][source]

Get the starting ids dictionary used for renumbering with ids greater than those in model.

Parameters
modelBDF

BDF object to get maximum ids from.

Returns
starting_id_dictdict {str

Dictionary from id type to starting id.

pyNastran.bdf.mesh_utils.bdf_renumber.get_starting_ids_dict_from_mapper(model, mapper)[source]
pyNastran.bdf.mesh_utils.bdf_renumber.superelement_renumber(bdf_filename, bdf_filename_out=None, size=8, is_double=False, starting_id_dict=None, cards_to_skip=None, log=None, debug=False)[source]

Renumbers a superelement

Parameters
bdf_filenamestr / BDF

str : a bdf_filename (string; supported) BDF : a BDF model that has been cross referenced and is fully valid (an equivalenced deck is not valid)

bdf_filename_outstr / None

str : a bdf_filename to write None : don’t write the BDF

sizeint; {8, 16}; default=8

the bdf write precision

is_doublebool; default=False

the field precision to write

starting_id_dictdict, None (default=None)

None : renumber everything starting from 1 dict : {key : starting_id}

keystr

the key (e.g. eid, nid, cid, …)

starting_idint, None

int : the value to start from None : don’t renumber this key

cards_to_skipList[str]; (default=None -> don’t skip any cards)

There are edge cases (e.g. FLUTTER analysis) where things can break due to uncross-referenced cards. You need to disable entire classes of cards in that case (e.g. all aero cards).

Returns
modelBDF()

a renumbered BDF object corresponding to bdf_filename_out

collapse_bad_quads Module

defines:
  • convert_bad_quads_to_tris(model, eids_to_check=None, xyz_cid0=None,

    min_edge_length=0.0)

pyNastran.bdf.mesh_utils.collapse_bad_quads.convert_bad_quads_to_tris(model: BDF, eids_to_check: List[int] = None, xyz_cid0: Optional[np.ndarray] = None, min_edge_length: float = 0.0) → None[source]

A standard quad is a nice rectangle. If an edge is collapsed, it’s a triangle. Change the element type with an inplace operation. Deletes any line elements created.

Parameters
modelBDF()

a BDF model that has not had it’s properties/load xref’d, but is valid such that it could

eidslist; (default=None -> all CQUAD4s)

the subset of element ids to check

xyz_cid0(n, 3) ndarray

nodes in cid=0

min_edge_lengthfloat; default=0.0

what is classified as “short”

.. warning:: Don’t cross reference properties/loads
.. todo:: check for bad xref
pyNastran.bdf.mesh_utils.collapse_bad_quads.delete_bad_tris(model: BDF, eids_to_check: List[int] = None, xyz_cid0: Optional[np.ndarray] = None, min_edge_length: float = 0.0) → None[source]

If an triangular edge is collapsed, it’s a line and should be deleted.

Parameters
modelBDF()

a BDF model that has not had it’s properties/load xref’d, but is valid such that it could

eidslist; (default=None -> all CTRIA3s)

the subset of element ids to check

xyz_cid0(n, 3) ndarray

nodes in cid=0

min_edge_lengthfloat; default=0.0

what is classified as “short”

.. warning:: Don’t cross reference properties/loads
.. todo:: check for bad xref

convert Module

defines:
  • convert(model, units_to, units=None)

pyNastran.bdf.mesh_utils.convert._convert_aero(model: BDF, xyz_scale: float, time_scale: float, force_scale: float) → None[source]
Converts the aero cards
  • CAEROx, PAEROx, SPLINEx, AECOMP, AELIST, AEPARAM, AESURF

Supports: AERO, AEROS, CAERO1, CAERO2, TRIM*, MONPNT1, FLUTTER FLFACT-rho/vel

GUST, AESURF, PAERO2

Skips: PAERO1, AESTAT, AESURFS, AECOMP, AELIST Doesn’t support:CAERO3-5, PAERO3-5, SPLINEx, AEPARAM, AELINK, AEPRESS, AEFORCE, *probably not done

pyNastran.bdf.mesh_utils.convert._convert_constraints(model: BDF, xyz_scale: float) → None[source]

Converts the spc/mpcs

Supports: SPC1, SPC, SPCAX Implicitly supports: MPC, MPCADD, SPCADD

pyNastran.bdf.mesh_utils.convert._convert_coordinates(model: BDF, xyz_scale: float) → None[source]

Converts the coordinate systems

Supports: CORD1x, CORD2x

pyNastran.bdf.mesh_utils.convert._convert_dconstr(model: BDF, dconstr: DCONSTR, pressure_scale: float) → None[source]

helper for _convert_optimization

pyNastran.bdf.mesh_utils.convert._convert_desvars(desvars, scale)[source]

scales the DVPREL/DVCREL/DVMREL DESVAR values

pyNastran.bdf.mesh_utils.convert._convert_dvcrel1(dvcrel: Union[DVCREL1, DVCREL2], xyz_scale: float) → float[source]

helper for _convert_optimization

pyNastran.bdf.mesh_utils.convert._convert_dvprel1(dvprel, xyz_scale: float, mass_scale: float, force_scale: float, time_scale: float) → float[source]

helper for _convert_optimization

pyNastran.bdf.mesh_utils.convert._convert_elements(model: BDF, xyz_scale: float, time_scale: float, mass_scale: float, force_scale: float) → None[source]

Converts the elements

Supports: CTRIA3, CTRIA6, CTRIAR, CQUAD4, CQUAD8, CQUADR,

CELAS2, CELAS4, CDAMP2, CDAMP4, CBUSH, CONROD, CBAR, CBEAM, GENEL, CONM2, CMASS4

SkipsCELAS1, CELAS3, CDAMP3, CDAMP5, CCONEAX,

CROD, CTUBE, CVISC, CBUSH1D, CQUAD, CSHEAR, CTRIAX, CTRIAX6, CTETRA, CPENTA, CHEXA, CPYRAM, CMASS1, CMASS3,

NX Skips: CTRAX3, CTRAX6, CPLSTN3, CPLSTN6, CPLSTN4’, CPLSTN8, CQUADX4, CQUADX8 *intentionally

pyNastran.bdf.mesh_utils.convert._convert_loads(model: BDF, xyz_scale: float, time_scale: float, force_scale: float, temperature_scale: float) → None[source]

Converts the loads

Supports:
  • dloads: RLOAD1*, TLOAD1*

  • loads: FORCE, FORCE1, FORCE2, MOMENT, MOMENT1, MOMENT2

    GRAV, ACCEL1, PLOAD, PLOAD1, PLOAD2, PLOAD4, RANDPS

  • combinations: DLOAD, LOAD

  • probably not done

pyNastran.bdf.mesh_utils.convert._convert_materials(model: BDF, xyz_scale: float, mass_scale: float, force_scale: float, temperature_scale: float) → None[source]

Converts the materials

Supports: MAT1, MAT2, MAT3, MAT8, MAT9, MAT10, MAT11

pyNastran.bdf.mesh_utils.convert._convert_nodes(model: BDF, xyz_scale: bool) → None[source]

Converts the nodes

Supports: GRID

pyNastran.bdf.mesh_utils.convert._convert_optimization(model: BDF, xyz_scale: float, mass_scale: float, force_scale: float, time_scale: float) → None[source]

Converts the optimization objects

Limited Support: DESVAR, DCONSTR, DVCREL1, DVPREL1

pyNastran.bdf.mesh_utils.convert._convert_pbar(scales: Set[str], prop: PBAR, xyz_scale: float, area_scale: float, area_moi_scale: float, nsm_bar_scale: float) → None[source]

converts a PBAR

pyNastran.bdf.mesh_utils.convert._convert_pbeam(scales: Set[str], prop: PBEAM, xyz_scale: float, area_scale: float, area_moi_scale: float, nsm_bar_scale: float) → None[source]

converts a PBEAM

pyNastran.bdf.mesh_utils.convert._convert_pbeam3(scales: Set[str], prop: PBEAM3, xyz_scale: float, area_scale: float, area_moi_scale: float, nsm_bar_scale: float) → None[source]

converts a PBEAM3

pyNastran.bdf.mesh_utils.convert._convert_pbush(scales: Set[str], prop: PBUSH, velocity_scale: float, mass_scale: float, stiffness_scale: float, log: SimpleLogger) → None[source]
pyNastran.bdf.mesh_utils.convert._convert_pbush1d(model: BDF, scales: Set[str], prop: PBUSH1D, xyz_scale: float, area_scale: float, mass_scale: float, damping_scale: float, stiffness_scale: float) → None[source]
pyNastran.bdf.mesh_utils.convert._convert_properties(model: BDF, xyz_scale: float, time_scale: float, mass_scale: float, force_scale: float, temperature_scale: float) → None[source]

Converts the properties

Supports: PELAS, PDAMP, PDAMP5, PVISC, PROD, PBAR, PBARL, PBEAM, PBEAML,

PSHELL, PSHEAR, PCOMP, PCOMPG, PELAS, PTUBE, PBUSH, PCONEAX, PGAP, PBUSH1D

Skips : PSOLID, PLSOLID, PLPLANE, PIHEX

Skips are unscaled (intentionally)

pyNastran.bdf.mesh_utils.convert._get_dload_scale(dload, scales: Set[str], xyz_scale: float, velocity_scale: float, accel_scale: float, force_scale: float) → None[source]

LOAD assumes force

pyNastran.bdf.mesh_utils.convert._log_scales(log: SimpleLogger, scale_map: Dict[str, str], scales: Set[str], keys_to_skip={})[source]
pyNastran.bdf.mesh_utils.convert._scale_caero(caero, xyz_scale: float, xyz_aefacts) → None[source]
pyNastran.bdf.mesh_utils.convert._scale_term(name: str, coeffs: List[float], terms: List[float], scales: List[float]) → Tuple[float, str][source]
pyNastran.bdf.mesh_utils.convert._set_wtmass(model: BDF, gravity_scale: float) → None[source]

set the PARAM,WTMASS

ft-lbm-s-lbf-psf : 1. / 32.2 in-lbm-s-lbf-psi : 1. / (32.2*12) m-kg-s-N-Pa : 1. mm-Mg-s-N-Mpa : 1. in-slinch-s-lbf-psi : 1. ft-slug-s-lbf-psf : 1. in-slug-s-lbf-psi : 1 / 12.

1 slug * 1 ft/s^2 = 1 lbf 1 slinch * 1 in/s^2 = 1 lbf 1 slinch = 12 slug

F = m*a 386 lbf = 1 slinch * 386 * in/s^2 32 lbf = 1 slug * 32 * ft/s^2 1 N = 1 kg * 9.8 m/s^2

1 lbf = g_scale * 1 slinch * 1 in/s^2 1 lbf = g_scale * 12 slug * 1 in/s^2 –> g_scale = 1/12.

pyNastran.bdf.mesh_utils.convert._setup_scale_by_terms(scales: List[float], terms: List[str], quiet: bool = False) → Tuple[float, float, float][source]

determines the mass, length, time scaling factors

pyNastran.bdf.mesh_utils.convert.convert(model: BDF, units_to: List[str], units: Optional[List[str]] = None) → None[source]

Converts a model from a set of defined units

Parameters
modelBDF

cross references the model (default=True)

units_toList[str]

[length, mass, time] length = {in, ft, m, cm, mm} mass = {g, kg, Mg, lbm, slug, slinch} time = {s}

unitsList[str]

overwrites model.units

pyNastran.bdf.mesh_utils.convert.convert_length(length_from, length_to)[source]

Determines the length scale factor

We create a gravity_scale_length for any non-standard unit (ft, m)

pyNastran.bdf.mesh_utils.convert.convert_mass(mass_from: str, mass_to: str, log: SimpleLogger) → Tuple[float, float, float][source]

determines the mass, weight, gravity scale factor

We apply a gravity_scale_mass for any unit not {kg, slug}. Then we convert to N.

So for SI, if we have kg, we have a base unit, and the length is assumed to be m, so we have a consistent system and gravity_scale_mass is 1.0.

For lbm:

F = m*a 1 lbf = 1 lbm * 1 ft/s^2 32 lbf = 1 slug * 32 ft/s^2 gscale = 1/g F = gscale * m * a 1 lbf = gscale * 1 lbm * 32 ft/s^2 –> gscale = 1/32

For slug:

F = gscale * m * a 32 lbf = gscale * 1 slug * 32 ft/s^2 –> gscale = 1

For slinch:

F = gscale * m * a 386 lbf = gscale * 1 slinch * 12*32 in/s^2 1 slinch = 12 slug 12 in = 1 ft 386 lbf = gscale * 12 slug * 32 ft/s^2 –> gscale = 1

TODO: slinch/slug not validated

pyNastran.bdf.mesh_utils.convert.get_scale_factors(units_from, units_to, log)[source]

[length, mass, time] [in, lb, s]

pyNastran.bdf.mesh_utils.convert.scale_by_terms(bdf_filename: Union[BDF, str], terms: List[float], scales: List[float], bdf_filename_out: Optional[str] = None, encoding: Optional[str] = None, log=None, debug: bool = True) → BDF[source]

Scales a BDF based on factors for 3 of the 6 independent terms

Parameters
bdf_filenamestr / BDF()

a BDF filename

termsList[str]; length=3

the names {M, L, T, F, P, V, A, rho} mass, length, time, force, pressure, velocity, area, mass_density

scalesList[float]; length=3

the scaling factors

bdf_filename_outstr; default=None

a BDF filename to write

Returns
modelBDF()

the scaled BDF

pyNastran.bdf.mesh_utils.convert.scale_model(model: BDF, xyz_scale: float, mass_scale: float, time_scale: float, force_scale: float, gravity_scale: float, convert_nodes: bool = True, convert_elements: bool = True, convert_properties: bool = True, convert_materials: bool = True, convert_aero: bool = True, convert_constraints: bool = True, convert_loads: bool = True, convert_optimization: bool = True)[source]

Performs the model scaling

delete_bad_elements Module

defines:
  • model = delete_bad_shells(model, max_theta=175., max_skew=70., max_aspect_ratio=100.,

    max_taper_ratio=4.0)

  • eids_to_delete = get_bad_shells(model, xyz_cid0, nid_map, max_theta=175., max_skew=70.,

    max_aspect_ratio=100., max_taper_ratio=4.0)

pyNastran.bdf.mesh_utils.delete_bad_elements._is_bad_quad(eid: int, p1, p2, p3, p4, log: cpylog.SimpleLogger, max_aspect_ratio: float, min_theta_quad: float, max_theta: float, max_skew: float, max_taper_ratio: float, max_warping: float) → bool[source]

identifies if a CQUAD4 has poor quality

pyNastran.bdf.mesh_utils.delete_bad_elements._is_bad_tri(eid: int, p1, p2, p3, log: cpylog.SimpleLogger, max_aspect_ratio: float, min_theta_tri: float, max_theta: float, max_skew: float) → bool[source]

identifies if a CTRIA3 has poor quality

pyNastran.bdf.mesh_utils.delete_bad_elements.delete_bad_shells(model: pyNastran.bdf.bdf.BDF, min_theta: float = 0.1, max_theta: float = 175.0, max_skew: float = 70.0, max_aspect_ratio: float = 100.0, max_taper_ratio: float = 4.0, max_warping: float = 90.0)[source]

Removes bad CQUAD4/CTRIA3 elements

Parameters
modelBDF ()

this should be equivalenced

min_thetafloat; default=0.1

the maximum interior angle (degrees)

max_thetafloat; default=175.

the maximum interior angle (degrees)

max_skewfloat; default=70.

the maximum skew angle (degrees)

max_aspect_ratiofloat; default=100.

the max aspect ratio

taper_ratiofloat; default=4.0

the taper ratio; applies to CQUAD4s only

max_warping: float: default=20.0

the maximum warp angle (degrees)

pyNastran.bdf.mesh_utils.delete_bad_elements.element_quality(model, nids=None, xyz_cid0=None, nid_map=None)[source]

Gets various measures of element quality

Parameters
modelBDF()

a cross-referenced model

nids(nnodes, ) int ndarray; default=None

the nodes of the model in sorted order includes GRID, SPOINT, & EPOINTs

xyz_cid0(nnodes, 3) float ndarray; default=None

the associated global xyz locations

nid_mapDict[nid]->index; default=None

a mapper dictionary

Returns
qualityDict[name]

Various quality metrics names : min_interior_angle, max_interior_angle, dideal_theta,

max_skew_angle, max_aspect_ratio, area_ratio, taper_ratio, min_edge_length

valuesThe result is np.nan if element type does not define

the parameter. For example, CELAS1 doesn’t have an aspect ratio.

Notes

  • pulled from nastran_io.py

pyNastran.bdf.mesh_utils.delete_bad_elements.get_bad_shells(model: pyNastran.bdf.bdf.BDF, xyz_cid0, nid_map, min_theta: float = 0.1, max_theta: float = 175.0, max_skew: float = 70.0, max_aspect_ratio: float = 100.0, max_taper_ratio: float = 4.0, max_warping: float = 60.0) → List[int][source]

Get the bad shell elements

Parameters
modelBDF()

the model object

xyz_cid0(N, 3) float ndarray

the xyz coordinates in cid=0

nid_mapdict[nid]
nidint

the node id

indexint

the index of the node id in xyz_cid0

min_thetafloat; default=0.1

the maximum interior angle (degrees)

max_thetafloat; default=175.

the maximum interior angle (degrees)

max_skewfloat; default=70.

the maximum skew angle (degrees)

max_aspect_ratiofloat; default=100.

the max aspect ratio

taper_ratiofloat; default=4.0

the taper ratio; applies to CQUAD4s only

max_warping: float: default=60.0

the maximum warp angle (degrees)

Returns
eids_failedList[int]

element ids that fail the criteria

shells with a edge length=0.0 are automatically added
pyNastran.bdf.mesh_utils.delete_bad_elements.get_min_max_theta(faces, all_node_ids, nid_map, xyz_cid0)[source]

get the min/max thetas for CTETRA, CPENTA, CHEXA, CPYRAM

pyNastran.bdf.mesh_utils.delete_bad_elements.get_node_map(model)[source]

gets an nid->inid mapper

pyNastran.bdf.mesh_utils.delete_bad_elements.quad_quality(element, p1, p2, p3, p4)[source]

gets the quality metrics for a quad

pyNastran.bdf.mesh_utils.delete_bad_elements.tri_quality(p1, p2, p3)[source]

gets the quality metrics for a tri

export_mcids Module

Defines:
  • nodes, bars = export_mcids(bdf_filename, csv_filename=None)

pyNastran.bdf.mesh_utils.export_mcids._add_elements(nid: int, eid: int, nodes: List[Tuple[int, float, float, float]], bars: List[Tuple[int, int, int]], centroid: numpy.ndarray, iaxis: numpy.ndarray, jaxis: numpy.ndarray, export_both_axes: bool, export_xaxis: bool) → Tuple[int, int][source]

adds the element data

pyNastran.bdf.mesh_utils.export_mcids._export_coord_axes(nodes, bars, csv_filename: str)[source]

save the coordinate systems in a csv file

pyNastran.bdf.mesh_utils.export_mcids._export_quad(model: pyNastran.bdf.bdf.BDF, elem, nodes, iply: int, nid: int, eid: int, bars: List[List[int]], export_both_axes: bool, export_xaxis: bool, consider_property_rotation: bool) → Tuple[int, int][source]

helper method for export_mcids

pyNastran.bdf.mesh_utils.export_mcids._export_quad_all(model: pyNastran.bdf.bdf.BDF, elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], nplies: int, nids: Dict[int, int], nodes: Dict[int, List[numpy.ndarray]], bars: Dict[int, List[Tuple[int, int]]]) → None[source]

helper method for export_mcids

pyNastran.bdf.mesh_utils.export_mcids._export_tri_all(model: pyNastran.bdf.bdf.BDF, elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], nplies: int, nids: Dict[int, int], nodes: Dict[int, List[numpy.ndarray]], bars: Dict[int, List[Tuple[int, int]]]) → None[source]

helper method for export_mcids

pyNastran.bdf.mesh_utils.export_mcids._export_tria(model: pyNastran.bdf.bdf.BDF, elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], nodes, iply: int, nid: int, eid: int, bars, export_both_axes: bool, export_xaxis: bool, consider_property_rotation: bool) → Tuple[int, int][source]

helper method for export_mcids

pyNastran.bdf.mesh_utils.export_mcids._export_xaxis(nid: int, nodes, bars, centroid, iaxis) → int[source]
pyNastran.bdf.mesh_utils.export_mcids._get_elements(model, eids)[source]
pyNastran.bdf.mesh_utils.export_mcids._get_quad_vectors(elem: pyNastran.bdf.cards.elements.shell.CQUAD4)[source]
pyNastran.bdf.mesh_utils.export_mcids._get_tri_vectors(elem: pyNastran.bdf.cards.elements.shell.CTRIA3)[source]
pyNastran.bdf.mesh_utils.export_mcids._make_element_coord_quad(elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], pid_ref, nids, nodes, bars)[source]
pyNastran.bdf.mesh_utils.export_mcids._make_element_coord_tri(elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], pid_ref, nids, nodes, bars)[source]
pyNastran.bdf.mesh_utils.export_mcids._rotate_coords(elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], pid_ref, nplies: int, nids, nodes, bars, dxyz, centroid, imat, jmat, normal)[source]
pyNastran.bdf.mesh_utils.export_mcids._rotate_mcid(elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], pid_ref: Union[pyNastran.bdf.cards.properties.shell.PCOMP, pyNastran.bdf.cards.properties.shell.PCOMPG, pyNastran.bdf.cards.properties.shell.PSHELL], iply: int, imat: numpy.ndarray, jmat: numpy.ndarray, normal: numpy.ndarray, consider_property_rotation: bool = True) → Tuple[numpy.ndarray, numpy.ndarray][source]

Rotates a material coordinate system. Assumes the element theta/mcid has already been acounted for.

pyNastran.bdf.mesh_utils.export_mcids._rotate_single_coord(elem: Union[pyNastran.bdf.cards.elements.shell.CTRIA3, pyNastran.bdf.cards.elements.shell.CTRIA6, pyNastran.bdf.cards.elements.shell.CQUAD4, pyNastran.bdf.cards.elements.shell.CQUAD8, pyNastran.bdf.cards.elements.shell.CTRIAR, pyNastran.bdf.cards.elements.shell.CQUADR], pid_ref, iply: int, nid, eid, nodes, bars, dxyz: float, centroid: numpy.ndarray, imat: numpy.ndarray, jmat: numpy.ndarray, normal: numpy.ndarray, export_both_axes: bool, export_xaxis: bool, consider_property_rotation: bool) → Tuple[int, int][source]
pyNastran.bdf.mesh_utils.export_mcids.export_mcids(bdf_filename: Union[pyNastran.bdf.bdf.BDF, str], csv_filename: Optional[str] = None, eids: Optional[List[int]] = None, export_xaxis: bool = True, export_yaxis: bool = True, consider_property_rotation: bool = True, iply: int = 0, log=None, debug=False)[source]

Exports the element material coordinates systems for non-isotropic materials.

Parameters
bdf_filenamestr/BDF

a bdf filename or BDF model

csv_filenamestr; default=None

str : the path to the output csv None : don’t write a CSV

eidsList[int]

the element ids to consider

export_xaxisbool; default=True

export the x-axis

export_yaxisbool; default=True

export the x-axis

consider_property_rotationbool; default=True

rotate the coordinate system

iplyint; default=0

TODO: not validated the ply to consider

pid_to_npliesDict[int pid, int nplies]; default=None -> auto

optional dictionary to speed up analysis

PSHELL

iply location —- ——–

0 mid1 or mid2 1 mid1 2 mid2 3 mid3 4 mid4

PCOMP/PCOMPG

iply location —- ——– 0 layer1 1 layer2

Returns
nodes(nnodes, 3) float list

the nodes

bars(nbars, 2) int list

the “bars” that represent the x/y axes of the coordinate systems

pyNastran.bdf.mesh_utils.export_mcids.export_mcids_all(bdf_filename: Union[pyNastran.bdf.bdf.BDF, str], eids: Optional[List[int]] = None, log=None, debug=False)[source]

Exports the element material coordinates systems for non-isotropic materials.

Note that for two quads identically oriented/numbered PSHELL quads with theta different between the two, the mcid will be different.

Parameters
bdf_filenamestr/BDF

a bdf filename or BDF model

csv_filenamestr; default=None

str : the path to the output csv None : don’t write a CSV

eidsList[int]

the element ids to consider

PSHELL

iply location —- ——–

0 mid1 or mid2 1 mid1 2 mid2 3 mid3 4 mid4

PCOMP/PCOMPG

iply location —- ——– 0 layer1 1 layer2

Returns
nodes(nnodes, 3) float list

the nodes

bars(nbars, 2) int list

the “bars” that represent the x/y axes of the coordinate systems

pyNastran.bdf.mesh_utils.export_mcids.get_pid_ref_prop_type(model: pyNastran.bdf.bdf.BDF, elem) → Tuple[Union[pyNastran.bdf.cards.properties.shell.PCOMP, pyNastran.bdf.cards.properties.shell.PCOMPG, pyNastran.bdf.cards.properties.shell.PSHELL], str][source]

helper method for export_mcids

pyNastran.bdf.mesh_utils.export_mcids.get_pid_to_nplies(model: pyNastran.bdf.bdf.BDF) → Tuple[Dict[int, int], int][source]

mirror_mesh Module

This file defines:
  • model, nid_offset, eid_offset = bdf_mirror(bdf_filename, plane=’xz’)

  • model, nid_offset, eid_offset = write_bdf_symmetric(

    bdf_filename, out_filename=None, encoding=None, size=8, is_double=False, enddata=None, close=True, plane=’xz’)

pyNastran.bdf.mesh_utils.mirror_mesh.__mirror_elements(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int, eid_offset: int, cid_offset: int, plane: str = 'xz') → None[source]

mirrors model.elements

pyNastran.bdf.mesh_utils.mirror_mesh.__mirror_masses(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int, eid_offset: int) → None[source]

mirrors model.masses

pyNastran.bdf.mesh_utils.mirror_mesh.__mirror_mpcs(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int) → None[source]

mirrors model.rigid_elements

pyNastran.bdf.mesh_utils.mirror_mesh.__mirror_rigid_elements(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int, eid_offset: int) → None[source]

mirrors model.rigid_elements

pyNastran.bdf.mesh_utils.mirror_mesh._asymmetrically_mirror_coords(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, cids_nominal_set: Set[int], cid_offset: int, plane: str = 'xz') → None[source]

we’ll leave i the same, flip j, and invert k

pyNastran.bdf.mesh_utils.mirror_mesh._asymmetrically_mirror_coords2(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, cids_nominal_set: Set[int], cid_offset: int, plane: str = 'xz') → None[source]

We’ll invert i, but not j, which will invert k.

This will allow us to mirror material coordinate systems (defined in x). Additionally, we can mirror CGAP coordinate systems (defined in x) as well as some arbitrary y-direction. We’ll try to make y look mirrored.

pyNastran.bdf.mesh_utils.mirror_mesh._get_cid_offset(model: pyNastran.bdf.bdf.BDF, use_cid_offset: bool) → int[source]
pyNastran.bdf.mesh_utils.mirror_mesh._get_eid_offset(model: pyNastran.bdf.bdf.BDF, use_eid_offset: bool) → int[source]
pyNastran.bdf.mesh_utils.mirror_mesh._mirror_aero(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int, plane: str = 'xz') → None[source]

Mirrors the aero cards

Considers:
  • AEROS

  • doesn’t consider sideslip

  • CAERO1

  • doesn’t consider sideslip

  • considers Cp

  • considers lchord/lspan/nchord/nspan

  • SPLINE1 - handle boxes

  • SET1 - handle nodes

  • AELIST - handle boxes

  • AESURF - only supports names of length 7 or less (appends an M to the name) - handles AELIST - doesn’t handle coords well - doesn’t handle second AESURF

Doesnt consider:
  • AERO

  • AEFORCE

  • AEPRES

  • CAERO2/3/4/5

  • PAERO1/2/3/4/5

  • AESURFS

pyNastran.bdf.mesh_utils.mirror_mesh._mirror_elements(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int, use_eid_offset: bool = True, plane: str = 'xz') → int[source]

Mirrors the elements

Parameters
modelBDF

the base model

modelBDF

the mirrored model

mirror_modelBDF

the mirrored model

nid_offsetint

the node id offset

use_eid_offsetbool; default=True

what is this for???

elements:
0dCELAS1, CELAS2, CELAS3, CELAS4, CDAMP1, CDAMP2, CDAMP3, CDAMP4, CDAMP5

CFAST, CBUSH, CBUSH1D

1d: CROD, CONROD, CTUBE, CBAR, CBEAM, CBEAM3 2d : CTRIA3, CQUAD4, CTRIA6, CQUAD8, CQUAD, CTRIAR, CQUADR 3d : ??? missing : CVISC, CTRIAX, CTRIAX6, CQUADX, CQUADX8, CCONEAX

rigid_elements:

loaded: RBE2, RBE3, RBAR missing: RBAR1

mass_elements:

loaded: CONM2 missing CONM1, CMASS1, CMASS2, CMASS3, CMASS4

plotels:

loaded: PLOTEL missing: ???

Notes

Doesn’t handle CBAR/CBEAM offsets Doesn’t handle CBEAM SPOINTs Do I need to invert the solids?

pyNastran.bdf.mesh_utils.mirror_mesh._mirror_loads(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, nid_offset: int = 0, eid_offset: int = 0) → None[source]

Mirrors the loads. A mirrored force acts in the same direction.

Considers:
  • PLOAD4
    • no coordinate systems (assumes cid=0)

  • FORCE, FORCE1, FORCE2, MOMENT, MOMENT1, MOMENT2

  • PLOAD, PLOAD2

  • TEMP, QVOL, QHBDY, QBDY1, QBDY2, QBDY3

pyNastran.bdf.mesh_utils.mirror_mesh._mirror_nodes(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, plane: str = 'xz') → Tuple[int, str][source]

Mirrors the GRIDs

Warning

doesn’t consider coordinate systems; it could, but you’d need 20 new coordinate systems

Warning

doesn’t mirror SPOINTs, EPOINTs

pyNastran.bdf.mesh_utils.mirror_mesh._mirror_nodes_plane(model: pyNastran.bdf.bdf.BDF, mirror_model: pyNastran.bdf.bdf.BDF, plane: Any, use_nid_offset: bool = True) → Tuple[int, str][source]

Mirrors the GRIDs about an arbitrary plane

Parameters
modelBDF

the original geometry

mirror_modelBDF

the location of the new geometry

plane(3,3) float ndarray

3 vectors that defines the origin, zaxis and xzplane; same as a CORD2R

use_nid_offsetbool

should the node offset be applied

Returns
nid_offsetint

the node id offset

planestr

the sorted plane; ZX -> xz

Warning

doesn’t consider coordinate systems; it could, but you’d need 20 new coordinate systems

Warning

doesn’t mirror SPOINTs, EPOINTs ..

https://mathinsight.org/distance_point_plane
pyNastran.bdf.mesh_utils.mirror_mesh._plane_to_iy(plane: str) → Tuple[int, str][source]

gets the index fo the mirror plane

pyNastran.bdf.mesh_utils.mirror_mesh.bdf_mirror(bdf_filename: Union[str, pyNastran.bdf.bdf.BDF], plane: str = 'xz', log=None, debug: bool = True)[source]

Mirrors the model about the symmetry plane

Parameters
bdf_filenamestr / BDF()

str : the bdf filename BDF : the BDF model object

planestr; {‘xy’, ‘yz’, ‘xz’}; default=’xz’

the plane to mirror about xz : +y/-y yz : +x/-x xy : +z/-z

Returns
modelBDF()

BDF : the BDF model object

nid_offsetint

the offset node id

eid_offsetint

the offset element id

pyNastran.bdf.mesh_utils.mirror_mesh.bdf_mirror_plane(bdf_filename: Union[str, pyNastran.bdf.bdf.BDF], plane: Any, mirror_model=None, log=None, debug: bool = True, use_nid_offset: bool = True)[source]

mirrors a model about an arbitrary plane

pyNastran.bdf.mesh_utils.mirror_mesh.write_bdf_symmetric(bdf_filename: Union[str, pyNastran.bdf.bdf.BDF], out_filename=None, encoding=None, size: int = 8, is_double: bool = False, enddata: Optional[bool] = None, close: bool = True, plane: str = 'xz', log=None)[source]

Mirrors the model about the symmetry plane

Parameters
bdf_filenamestr / BDF()

str : the bdf filename BDF : the BDF model object

out_filenamevaries; default=None

str - the name to call the output bdf file - a file object StringIO() - a StringIO object None - pops a dialog

encodingstr; default=None -> system specified encoding

the unicode encoding latin1, and utf8 are generally good options

sizeint; {8, 16}

the field size

is_doublebool; default=False

False : small field True : large field

enddatabool; default=None

bool - enable/disable writing ENDDATA None - depends on input BDF

closebool; default=True

should the output file be closed

planestr; {‘xy’, ‘yz’, ‘xz’}; default=’xz’

the plane to mirror about xz : +y/-y yz : +x/-x xy : +z/-z

Returns
modelBDF()

BDF : the BDF model object

nid_offsetint

the offset node id

eid_offsetint

the offset element id

Notes

Updates the BDF object to be symmetric
  • see bdf_mirror if you don’t want to write the model

Doesn’t equivalence nodes on the centerline.

Considers
  • nodes : GRID

  • elements, rigid_elements, mass_elements : see _mirror_elements

  • loads : see _mirror_loads

  • aero cards : see _mirror_aero

extract_bodies Module

defines:
  • extract_bodies(bdf_filename)

pyNastran.bdf.mesh_utils.extract_bodies.extract_bodies(bdf_filename, mpc_id=0)[source]

Finds the isolated bodies

Parameters
bdf_filenamestr/BDF

str : the path the the *.bdf file BDF : a BDF() boject

mpc_idint; default=0

0 : consider all MPCs >0 : use this MPC set not supported

Considers:
  • elements

  • rigid_elements

Doesn’t consider:
  • elements_mass

  • MPC

  • MPCADD

  • DMIx

Doesn’t support:
  • xref

  • duplicate element ids

  • large values

find_closest_nodes Module

defines:
  • nids_close = find_closest_nodes(nodes_xyz, nids, xyz_compare, neq_max, tol)

  • ieq = find_closest_nodes_index(nodes_xyz, xyz_compare, neq_max, tol)

pyNastran.bdf.mesh_utils.find_closest_nodes._not_equal_nodes_build_tree(nodes_xyz: Any, xyz_compare: Any, tol: float, neq_max: int = 4, msg: str = '') -> (typing.Any, <class 'numpy.ndarray'>, <class 'numpy.ndarray'>)[source]

helper function for bdf_equivalence_nodes

Parameters
nodes_xyz(Nnodes, 3) float ndarray

the source points

xyz_compare(Ncompare, 3) float ndarray

the xyz points to compare to

tolfloat

the max spherical tolerance

neq_maxint; default=4

the number of close nodes

msgstr; default=’’

error message

Returns
kdtcKDTree()

the kdtree object

ieqint ndarray

The indices of nodes_xyz where the nodes in xyz_compare are close??? neq_max = 1:

(N, ) int ndarray

neq_max > 1:

(N, N) int ndarray

slotsint ndarray

The indices of nodes_xyz where the nodes in xyz_compare are close??? neq_max = 1:

(N, ) int ndarray

neq_max > 1:

(N, N) int ndarray

msgstr; default=’’

error message

pyNastran.bdf.mesh_utils.find_closest_nodes.find_closest_nodes(nodes_xyz: Any, nids: Any, xyz_compare: Any, neq_max: int = 1, tol: Optional[float] = None, msg: str = '') → Any[source]

Finds the closest nodes to an arbitrary set of xyz points

Parameters
nodes_xyz(Nnodes, 3) float ndarray

the source points (e.g., xyz_cid0)

nids(Nnodes, ) int ndarray

the source node ids (e.g.; nid_cp_cid[:, 0])

xyz_compare(Ncompare, 3) float ndarray

the xyz points to compare to; xyz_to_find

tolfloat; default=None

the max spherical tolerance None : the whole model

neq_maxint; default=1

the number of “close” points

msgstr; default=’’

custom message used for errors

Returns
nids_close: (Ncompare, ) int ndarray

the close node ids

pyNastran.bdf.mesh_utils.find_closest_nodes.find_closest_nodes_index(nodes_xyz: Any, xyz_compare: Any, neq_max: int, tol: float, msg: str = '')[source]

Finds the closest nodes to an arbitrary set of xyz points

Parameters
nodes_xyz(Nnodes, 3) float ndarray

the source points

xyz_compare(Ncompare, 3) float ndarray

the xyz points to compare to

neq_maxint

the number of “close” points (default=4)

tolfloat

the max spherical tolerance

msgstr; default=’’

error message

Returns
slots(Ncompare, ) int ndarray

the indices of the close nodes corresponding to nodes_xyz

find_coplanar_elements Module

pyNastran.bdf.mesh_utils.find_coplanar_elements.find_coplanar_triangles(bdf_filename: Union[BDF, str], eids: Optional[List[int]] = None) → List[int][source]

Finds coplanar triangles

Parameters
bdf_filenameBDF/str

BDF: a model str: the path to the bdf input file

eidslist

the element ids to consider

Returns
coplanar_eidsList[int]

the elements that are coplanar

force_to_pressure Module

pyNastran.bdf.mesh_utils.force_to_pressure.force_to_pressure(bdf_filename, bdf_filename_out=None)[source]

converts FORCE cards to PLOAD4s for a shell model

free_edges Module

defines:

edges = free_edges(model, eids=None) edges = non_paired_edges(model, eids=None)

pyNastran.bdf.mesh_utils.free_edges._get_edge_to_eids_map(model, eids=None)[source]

helper method

pyNastran.bdf.mesh_utils.free_edges.free_edges(model: BDF, eids: Optional[List[int]] = None, maps=None) → List[Tuple[int, int]][source]

Gets the free edges for shell elements. A free edge is an edge that is only connected to 1 shell element.

Parameters
modelBDF()

the BDF model

eidsList[int]; default=None

a subset of elements to consider

mapsList[…] (default=None -> calculate)
the output from _get_maps(eids, map_names=None,

consider_0d=False, consider_0d_rigid=False, consider_1d=False, consider_2d=True, consider_3d=False)

Returns
edges: List[Tuple[int,int]]

list of node ids of each edges

pyNastran.bdf.mesh_utils.free_edges.non_paired_edges(model: BDF, eids: List[int] = None, maps=None) → List[Tuple[int, int]][source]

Gets the edges not shared by exactly 2 elements. This is useful for identifying rib/spar intersections.

Parameters
modelBDF()

the BDF model

eidsList[int]; default=None

a subset of elements to consider

mapsList[…] (default=None -> calculate)
the output from _get_maps(eids, map_names=None,

consider_0d=False, consider_0d_rigid=False, consider_1d=False, consider_2d=True, consider_3d=False)

Returns
non_paired_edgesList[(int nid1, int nid2), …]

the non-paired edges

free_faces Module

defines:
  • get_element_faces(model, element_ids=None)

  • get_solid_skin_faces(model)

  • write_skin_solid_faces(model, skin_filename,

    write_solids=False, write_shells=True, size=8, is_double=False, encoding=None)

pyNastran.bdf.mesh_utils.free_faces._write_shells(bdf_file, model, eid_set, face_map, eid_shell, pid_shell, mid_shell, mids_to_write)[source]

helper method for _write_skin_solid_faces

pyNastran.bdf.mesh_utils.free_faces._write_skin_solid_faces(model, skin_filename, face_map, nids_to_write, eids_to_write, mids_to_write, eid_set, eid_shell, pid_shell, mid_shell, write_solids=False, write_shells=True, size=8, is_double=False, encoding=None)[source]

helper method for write_skin_solid_faces

Parameters
modelBDF()

the BDF object

skin_filenamestr

the file to write

face_mapdict[sorted_face]

sorted_face : List[int, int, int] / List[int, int, int, int] face : List[int, int, int] / List[int, int, int, int]

nids_to_writeList[int, int, …]

list of node ids to write

eids_to_writeList[int, int, …]

list of element ids to write

mids_to_writeList[int, int, …]

list of material ids to write

eid_setSet[int]

is the type right???

eid_shellint

the next id to use for the shell id

pid_shellint

the next id to use for the shell property

mid_shellint

the next id to use for the shell material

write_solidsbool; default=False

write solid elements that have skinned faces

write_shellsbool; default=True

write shell elements

sizeint; default=/8

the field width

is_doublebool; default=False

double precision flag

encodingstr; default=None -> system default

the string encoding

pyNastran.bdf.mesh_utils.free_faces.get_element_faces(model: pyNastran.bdf.bdf.BDF, element_ids: Optional[List[int]] = None) → Any[source]

Gets the elements and faces that are skinned from solid elements. This includes internal faces.

Parameters
modelBDF()

the BDF object

element_idsList[int] / None

skin a subset of element faces default=None -> all elements

Returns
eid_faces(int, List[(int, int, …)])

value1 : element id value2 : face

pyNastran.bdf.mesh_utils.free_faces.get_solid_skin_faces(model: pyNastran.bdf.bdf.BDF) → Any[source]

Gets the elements and faces that are skinned from solid elements This doesn’t include internal faces.

Parameters
modelBDF()

the BDF object

Returns
eid_setDict[tuple(int, int, …)] = List[int]

key : sorted face value : list of element ids with that face

face_mapDict[tuple(int, int, …)] = List[int]

key : sorted face value : unsorted face

pyNastran.bdf.mesh_utils.free_faces.write_skin_solid_faces(model, skin_filename, write_solids=False, write_shells=True, size=8, is_double=False, encoding=None, punch=False, log=None)[source]

Writes the skinned elements

Parameters
modelBDF() or str

BDF : the BDF object str : bdf_filename and the read_bdf method is called

skin_filenamestr

the file to write

write_solidsbool; default=False

write solid elements that have skinned faces

write_shellsbool; default=False

write shell elements

sizeint; default=8

the field width

is_doublebool; default=False

double precision flag

encodingstr; default=None -> system default

the string encoding

loglogger; default=None

a python logging object

punchbool; default=False

is this a punch file; should be used by the read_bdf if model is a string unused

get_oml Module

defines:
  • eids_oml = get_oml_eids(bdf_filename, eid_start, theta_tol=30.,

    is_symmetric=True, consider_flippped_normals=True)

pyNastran.bdf.mesh_utils.get_oml.get_oml_eids(bdf_filename: Union[str, pyNastran.bdf.bdf.BDF, pathlib.PurePath, _io.StringIO], eid_start: int, theta_tol: float = 30.0, is_symmetric: bool = True, consider_flippped_normals: bool = True) → Tuple[pyNastran.bdf.bdf.BDF, Set[int]][source]

Extracts the OML faces (outer mold line) of a shell model. In other words, find all the shell elements touching the current element without crossing an MPC or rigid element.

Parameters
bdf_filenamestr or BDF()

the bdf filename

eid_startint

the element to start from

theta_tolfloat; default=30.

the angular tolerance in degrees

is_symmetricbool; default=True

is the y=0 plane considered to be part of the OML

consider_flippped_normalsbool; default=True

if you extracted the free faces from tets, you can get flipped normals this considers a 180 degree error to be 0.0, which will cause other problems

pyNastran.bdf.mesh_utils.get_oml.main()[source]

runs the test problem

remove_unused Module

defines some methods for cleaning up a model
  • model = remove_unused(bdf_filename, remove_nids=True, remove_cids=True,

    remove_pids=True, remove_mids=True)

pyNastran.bdf.mesh_utils.remove_unused._remove(model: pyNastran.bdf.bdf.BDF, nids_used, cids_used, pids_used, pids_mass_used, mids_used, spcs_used, mpcs_used, pconv_used, tableht_used, tableh1_used, unused_desvars_used, remove_nids=True, remove_cids=True, remove_pids=True, remove_mids=True, remove_spcs=True, remove_mpcs=True, unused_remove_desvars=True) → None[source]

actually removes the cards

pyNastran.bdf.mesh_utils.remove_unused._remove_thermal(model: pyNastran.bdf.bdf.BDF, pconv_used, tableht_used, tableh1_used) → None[source]

removes some thermal cards

pyNastran.bdf.mesh_utils.remove_unused._store_dresp1(model, ids, nids_used, pids_used)[source]

helper for remove_unused

pyNastran.bdf.mesh_utils.remove_unused._store_elements(card_type, model, ids, nids_used, pids_used, mids_used, cids_used)[source]
pyNastran.bdf.mesh_utils.remove_unused._store_loads(model, unused_card_type, unused_ids, nids_used, eids_used, cids_used)[source]

helper for remove_unused

pyNastran.bdf.mesh_utils.remove_unused._store_masses(card_type, model, ids, nids_used, pids_mass_used, cids_used) → None[source]

handles masses

pyNastran.bdf.mesh_utils.remove_unused._store_nsm(model, ids, pids_used)[source]

helper for remove_unused

pyNastran.bdf.mesh_utils.remove_unused.remove_unused(bdf_filename: str, remove_nids: bool = True, remove_cids: bool = True, remove_pids: bool = True, remove_mids: bool = True, remove_spcs: bool = True, remove_mpcs: bool = True, reset_type_to_id_map: bool = False) → pyNastran.bdf.bdf.BDF[source]

Takes an uncross-referenced bdf and removes unused data

removes unused:
  • nodes

  • properties

  • materials

  • coords

  • spcs

  • mpcs

cannot be removed:
  • loads

split_cbars_by_pin_flag Module

defines:
  • model, pin_flag_map = split_cbars_by_pin_flag(

    bdf_filename, pin_flags_filename=None, bdf_filename_out=None)

pyNastran.bdf.mesh_utils.split_cbars_by_pin_flag.split_cbars_by_pin_flag(bdf_filename, pin_flags_filename=None, bdf_filename_out=None, debug=False)[source]

Splits bar elements if they have a pin flag. That way you can each side of the element (A/B) a unique color based on the pin flag. This doesn’t split non-pin flagged bars.

Parameters
bdf_filenamestr; BDF

str : use the read_bdf method BDF : assume it’s a model

pin_flags_filenamestr; default=None

the pin flag file to write this is optional as you may need to define your own map

bdf_filename_outstr; default=None

write the updated deck

debugbool/None; default=True
used to set the logger if no logger is passed in

True: logs debug/info/error messages False: logs info/error messages None: logs error messages

Returns
modelBDF()

the BDF object

pin_flag_mapdict[eid]
eidint

the element id

pin_flagint

the bar pin flag

pyNastran.bdf.mesh_utils.split_cbars_by_pin_flag.write_pin_flag_map(pin_flag_map, pin_flags_filename)[source]

writes the pin flag map

split_elements Module

defines:
  • split_line_elements(bdf_model, eids, neids=2,

    eid_start=1, nid_start=1)

pyNastran.bdf.mesh_utils.split_elements.split_elements(bdf_filename)[source]

unimplemented method for splitting elements

pyNastran.bdf.mesh_utils.split_elements.split_line_elements(bdf_model, eids, neids=2, eid_start=1, nid_start=1)[source]

Splits a set of element ids

Parameters
eidsList[int]

element ids to split

neidsint; default=5

how many elements should a single bar be split into min=2

eid_startint; default=1

the starting element id

nid_startint; default=1

the starting node id

Returns
eids_outList[int]

the list of elements that have been added

eid_endint; default=1

the final element id

nid_endint; default=1

the final node id

A—–*—–B; neids=2
A–*–B; neids=4

utils Module

defines:

bdf merge (IN_BDF_FILENAMES)… [-o OUT_BDF_FILENAME]

bdf equivalence IN_BDF_FILENAME EQ_TOL

bdf renumber IN_BDF_FILENAME [-o OUT_BDF_FILENAME]

bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [–plane PLANE] [–tol TOL]

bdf export_mcids IN_BDF_FILENAME [-o OUT_GEOM_FILENAME]

bdf split_cbars_by_pin_flags IN_BDF_FILENAME [-o OUT_BDF_FILENAME]

pyNastran.bdf.mesh_utils.utils._filter_no_args(msg: str, argv: List[str], quiet: bool = False)[source]
pyNastran.bdf.mesh_utils.utils._union(xval, iunion, ix)[source]

helper method for filter

pyNastran.bdf.mesh_utils.utils.cmd_line(argv=None, quiet=False)[source]

command line interface to multiple other command line scripts

pyNastran.bdf.mesh_utils.utils.cmd_line_bin(argv=None, quiet=False)[source]

bins the model into nbins

pyNastran.bdf.mesh_utils.utils.cmd_line_convert(argv=None, quiet=False)[source]

command line interface to bdf_merge

pyNastran.bdf.mesh_utils.utils.cmd_line_create_vectorized_numbered(argv=None, quiet=False)[source]
pyNastran.bdf.mesh_utils.utils.cmd_line_equivalence(argv=None, quiet=False)[source]

command line interface to bdf_equivalence_nodes

pyNastran.bdf.mesh_utils.utils.cmd_line_export_caero_mesh(argv=None, quiet=False)[source]

command line interface to export_caero_mesh

pyNastran.bdf.mesh_utils.utils.cmd_line_export_mcids(argv=None, quiet=False)[source]

command line interface to export_mcids

pyNastran.bdf.mesh_utils.utils.cmd_line_filter(argv=None, quiet=False)[source]

command line interface to bdf filter

pyNastran.bdf.mesh_utils.utils.cmd_line_free_faces(argv=None, quiet=False)[source]

command line interface to bdf free_faces

pyNastran.bdf.mesh_utils.utils.cmd_line_merge(argv=None, quiet=False)[source]

command line interface to bdf_merge

pyNastran.bdf.mesh_utils.utils.cmd_line_mirror(argv=None, quiet=False)[source]

command line interface to write_bdf_symmetric

pyNastran.bdf.mesh_utils.utils.cmd_line_renumber(argv=None, quiet=False)[source]

command line interface to bdf_renumber

pyNastran.bdf.mesh_utils.utils.cmd_line_scale(argv=None, quiet=False)[source]
pyNastran.bdf.mesh_utils.utils.cmd_line_split_cbars_by_pin_flag(argv=None, quiet=False)[source]

command line interface to split_cbars_by_pin_flag

pyNastran.bdf.mesh_utils.utils.cmd_line_transform(argv=None, quiet=False)[source]

command line interface to export_caero_mesh