fem.mesh package

Submodules

fem.mesh.CreateStructure module

define structures in meshes

Examples

The following is a CLI example: >>> python3 CreateStructure.py –nefile elems_sphere.dyn –sphere

–sopts 0.0 0.0 -1.0 0.5

fem.mesh.CreateStructure.define_struct_type(args) str
Determine the type of structure being defined from the Boolean

input arguments

Parameters:

args (obj) – type of geometry

Returns:

struct_type (str)

Raises:

NotImplementedError – specified structure type not implemented

fem.mesh.CreateStructure.findStructElemIDs(elefile: str, structNodeIDs: dict) list

find elements that contain nodes in structNodeIDs

Parameters:
  • elefile (str) – element filename

  • structNodeIDs (dict) –

Returns:

(elems, structElemIds)

Raises:

ValueError – no structural elements found

fem.mesh.CreateStructure.findStructNodeIDs(nodefile: str, struct_type: str, sopts) dict

find nodes in given geometry

Find node IDs that fall within a specified geometry (sphere, layer, cube, ellipsoid).

Parameters:
  • nodefile (str) – nodes.dyn

  • struct_type (str) – sphere, layer, ellipsoid, cube

  • sopts – struct-specific parameters

Returns:

structNodeIDs (dict)

Raises:

ValueError – specified struct type not defined

fem.mesh.CreateStructure.main()
fem.mesh.CreateStructure.parse_cli()

read in CLI arguments

Returns:

CLI arguments

Return type:

args

fem.mesh.CreateStructure.write_struct_elems(nefile: str, partid: int, elems: list, structNodeIDs: dict, structElemIDs: dict)

Write new elem files with structure elems assigned a new part ID.

Parameters:
  • nefile (str) – new element file

  • partid (int) – new Part ID

  • elems (list) –

  • structNodeIDs (dict) –

  • structElemIDs (dict) –

fem.mesh.GaussExc module

Generate Gaussian distribution of point loads.

fem.mesh.GaussExc.calc_gauss_amp(node_xyz: list, center: tuple = (0.0, 0.0, - 2.0), sigma: tuple = (1.0, 1.0, 1.0), amp: float = 1.0, amp_cut: float = 0.05, sym: str = 'qsym')

calculated the Gaussian amplitude at the node

Parameters:
  • node_xyz (list) – x,y,z node coordinates

  • center (tuple) – x,y,z for Gaussian center (default = (0.0, 0.0, -2.0)

  • sigma (list) – x,y,z Guassian width (default = (1.0, 1.0, 1.0))

  • amp (float) – peak Gaussian source amplitude (default = 1.0)

  • amp_cut (float) – lower threshold (pct of max) for amplitude creating a point load (default = 0.05)

  • sym (str) – mesh symemetry (‘qsym’ [default], ‘hsym’, ‘none’)

Returns:

nodeGaussAmp - point load amplitude at the specified node

fem.mesh.GaussExc.calc_tukey_amp(node_xyz: tuple, center: tuple = (0.0, 0.0, - 2.0), sigma: tuple = (1.0, 1.0), tukey_length: float = 1.0, tukey_alpha: float = 0.25, amp: float = 1.0, amp_cut: float = 0.05, sym: str = 'qsym') float

calculated the Gaussian amplitude at the node

Parameters:
  • node_xyz (tuple) – x,y,z node coordinates

  • center (tuple) – x,y,z for excitation center (Default value = (0.0)

  • sigma (tuple) – list of x,y Guassian width

  • tukey_length (float) – length of axial extent, centered at center

  • tukey_alpha (float) – percentage of rolloff (see scipy documentation)

  • amp (float) – peak Gaussian source amplitude

  • amp_cut (float) – lower threshold (pct of max) for amplitude

  • sym (str) – mesh symemetry (qsym [default], hsym, none)

Returns:

point load amplitude at the specified node

Return type:

nodeGaussAmp (float)

fem.mesh.GaussExc.check_num_fields(fields: list, num_fields: int = 4)

check for 4 fields

Parameters:
  • fields – list (node ID, x, y, z)

  • num_fields (int) – default = 4

Returns:

Raises:

ValueError – unexpected number of node columns

fem.mesh.GaussExc.generate_loads(sigma: tuple, center: tuple, amp: float = 1.0, amp_cut: float = 0.05, sym: str = 'qsym', direction: int = - 3, loadfilename: str = 'loads.dyn', nodefile: str = 'nodes.dyn', tukey_length: float = 0.0, tukey_alpha: float = 0.25)
Parameters:
  • sigma (tuple) –

  • center (tuple) –

  • amp – (Default value = 1.0)

  • amp_cut – (Default value = 0.05)

  • sym – (Default value = “qsym”)

  • direction – (Default value = -3)

  • loadfilename – (Default value = “loads.dyn”)

  • nodefile – (Default value = “nodes.dyn”)

  • tukey_length – (Default value = 0.0)

  • tukey_alpha – (Default value = 0.25)

Returns:

fem.mesh.GaussExc.main()
fem.mesh.GaussExc.read_cli()

read CLI arguments

fem.mesh.GaussExc.read_node_positions(line: str) list

read node position fields from line in nodefile

Ignore lines that start with ‘$’ (comments) and ‘*’ keywords; Assume that all data entries are comma-delimited without spaces.

Parameters:

line (str) – single line string from nodefile

Returns:

1x4 float list of node ID, x, y, z; None if appropriate

Return type:

fields (list)

fem.mesh.GaussExc.read_process_nodes(sigma, center, sym='qsym', amp: float = 1.0, amp_cut: float = 0.05, nodefile: str = 'nodes.dyn', tukey_length: float = 0.0, tukey_alpha: float = 0.25) list

read nodes and determine if point load should be applied based on spatial position

Parameters:
  • sigma

  • center

  • sym (str) – default = ‘qsym’

  • amp (float) – amplitude (default = 1.0)

  • amp_cut (float) – lower amplitude threshold (default = 0.05)

  • nodefile (str) – default = ‘nodes.dyn’

  • tukey_length (float) – length of Tukey window (0.0 defaults to Gaussian)

  • tukey_alpha (float) – percentage of Tukey window to rolloff (Default value = 0.25)

Returns:

[nodeID, nodeGaussAmp]

Return type:

load_nodeID_amp (list)

fem.mesh.GaussExc.sym_scale_amp(fields: list, nodeGaussAmp: float, sym: str, search_tol: float = 0.0001) float

scale point load amplitude on symmetry faces / edges

Parameters:
  • fields (list) – node ID, x, y, z

  • nodeGaussAmp (float) – amplitude of point load

  • sym (str) – type of mesh symmetry (none, qsym, hsym)

  • search_tol (float) – spatial tolerance to find nearby nodes

Returns:

symmetry-scaled point load amplitude

Return type:

nodeGaussAmp (float)

Raises:

ValueError – invalid symmetry option specified

fem.mesh.GaussExc.tukey_z_scale(z: float, center: float, length: float, alpha: float = 0.25, points: int = 101) float
Parameters:
  • z (float) – z-coordinate

  • center (float) – center of Tukey window

  • length (float) – length of Tukey window

  • alpha (float) – rolloff (percentage of window) (Default value = 0.25)

  • points (int) – number of points in Tukey window (Default value = 101)

Returns:

scale, relative to 1.0

Return type:

z_scale (float)

fem.mesh.GaussExc.write_load_file(loadfilename: str, load_nodeID_amp, direction: int = - 3, header_comment: str = '$Generated by GaussExc.py\n')

write load file

Args:

loadfilename (str): load_nodeID_amp: list of int node ID, float amp direction (int): default = -3 (orientation (1, 2, 3) and sign) header_comment (str): (Default value = “$Generated by GaussExc.py

“)

Returns:

fem.mesh.GenMesh module

GenMesh – mesh generation

fem.mesh.GenMesh.calc_node_pos(xyz=(- 1.0, 0.0, - 1.0, 1.0, - 4.0, 0.0), numElem=(20, 20, 20))

Calculate nodal spatial positions based on CLI specs

Parameters:
  • xyz – xmin, xmax, ymin, ymax, zmin, zmax) (Default value = (-1.0)

  • numElem – (xEle, yEle, zEle)

Returns:

pos (list) - list of lists containing x, y, and z positions

Raises:
  • ValueError – wrong number of position range limits input

  • ValueError – min/max range swapped in input

fem.mesh.GenMesh.check_x0_y0(pos)

check model position

Check to make sure that nodes exist at (x, y) = (0, 0) so that the focus / peak of an ARF excitation is captured by the mesh.

Parameters:

pos – node positions

Raises:

RuntimeWarning – no (x, y) == (0, 0) position defined

Returns:

0/1 (1 = fail)

fem.mesh.GenMesh.main()
fem.mesh.GenMesh.parse_cli()

parse commandline arguments

Defines:

–nodefile [nodes.dyn] –elefile [elems.dyn] –partid [1] –xyz [(xmin, xmax, ymin, ymax,…)] –numElem [(x, y, z)]

Returns:

CLI arguments

Return type:

args

fem.mesh.GenMesh.run(xyz, numElem, nodefile: str = 'nodes.dyn', elefile: str = 'elems.dyn', partid: int = 1)
Parameters:
  • xyz (list) –

  • numElem (list) –

  • nodefile (str) – default = “nodes.dyn”

  • elefile (str) – default = “elems.dyn”

  • partid (int) – default = 1

fem.mesh.GenMesh.writeElems(numElem, partid=1, elefile='elems.dyn', header_comment='$ Generated by GenMesh.py')

write element file using calculated position data

Parameters:
  • pos – list of lists of x, y, z positions

  • str – elefile: elems.dyn

  • str – header_comment: what version / syntax of calling command

  • numElem

  • partid – (Default value = 1)

  • elefile – (Default value = “elems.dyn”)

  • header_comment – (Default value = “$ Generated by GenMesh.py”)

Returns:

elefile written

fem.mesh.GenMesh.writeNodes(pos, nodefile='nodes.dyn', header_comment='$ Generated by GenMesh.py')

write node file using calculated position data

Parameters:
  • pos – list of lists of x, y, z positions

  • nodefile – nodes.dyn (Default value = “nodes.dyn”)

  • header_comment (str) – what version / syntax of calling command

Returns:

nodes.dyn written (or specified filename)

fem.mesh.TopLoad module

Generate compression loads on top surface.

fem.mesh.TopLoad.extract_top_plane_nodes(nodefile, top_face)
Parameters:
  • nodefile – param top_face:

  • top_face

Returns:

planeNodeIDs

fem.mesh.TopLoad.generate_loads(loadtype='disp', direction=2, amplitude=- 1.0, loadfile='topload.dyn', nodefile='nodes.dyn', top_face=(0, 0, 0, 0, 0, 1), lcid=1)

apply loads to

Parameters:
  • loadtype (str) – disp’, ‘vel’, ‘accel’, ‘force’

  • direction (int) – 0 - x, 1 - y, 2 - z

  • amplitude (float) – scalar of load type

  • loadfile (str) – written loadfile name

  • nodefile (str) –

  • top_face (tuple) – constraintst to apply

  • lcid (int) – load curve ID

Returns:

fem.mesh.TopLoad.main()

TODO: way too complicated for now; refactor this

fem.mesh.TopLoad.read_cli()

read CLI args

fem.mesh.TopLoad.writeNodeLoads(loadfile, planeNodeIDs, loadtype, direction, amplitude, lcid)

Write load keyword file.

Parameters:
  • loadfile (str) – load filename

  • planeNodeIDS (ndarray) – array of node IDs

  • loadtype (str) – disp, vel, accel, force

  • direction (int) – 0-2

  • amplitude (float) –

  • lcid (int) – LCID

Returns:

None

fem.mesh.bc module

bc.py - apply boundary conditions to rectangular solid meshes

fem.mesh.bc.apply_face_bc_only(face_constraints, nodefile='nodes.dyn', bcfile='bc.dyn')

Driver function to apply node BCs just to faces.

Parameters:
  • face_constraints (tuple) –

    3x2 tuple of strings ((‘0,0,0,0,0,0’), (‘0,0,0,0,0,0’),

    (‘0,0,0,0,0,0’), (‘0,0,0,0,0,0’), (‘0,0,0,0,0,0’), (‘0,0,0,0,0,0’))

    Specify face BCs as ((xmin, xmax), (ymin, ymax), (zmin, zmax))

  • nodefile (str) – input file for node definitions (*NODE)

  • bcfile (str) – output file for boundary conditions (*BOUNDARY_SPC_NODE)

fem.mesh.bc.apply_nonreflect(face_constraints, edge_constraints, nodefile='nodes.dyn', bcfile='bc.dyn', segfile='nonreflect_segs.dyn')

driver function to generate non-reflecting boundaries

Parameters:
  • face_constraints (str) – vector of face constraints, ordered xmin to zmax

  • edge_constraints (str) – vector of edge constraints, ordered xmin to zmax

  • nodefile (str) – default - ‘nodes.dyn’

  • bcfile (str) – default - ‘bc.dyn’

  • segfile (str) – default - ‘nonreflect_segs.dyn’

Returns:

0 on success

fem.mesh.bc.apply_pml(pml_elems, face_constraints, edge_constraints, nodefile='nodes.dyn', elefile='elems.dyn', pmlfile='elems_pml.dyn', bcfile='bc.dyn', pml_partID=2)

driver function to apply PML boundary conditions

Parameters:
  • pml_elems (str) – 3x2 array of ints specifying thickness of PML elements (5–10) on each PML layer face_constraints: 3x2 array of strings, specifying the BCs on each face (3), min/max (2)

  • edge_constraints (str) – 1x6 vector of BCs on each edge

  • nodefile (str) – default - input file for the node definitions

  • elefile (str) – default - input file for the element definitions

  • pmlfile (str) – output file for the elements w/ PMLs

  • bcfile (str) – output file for the boundary conditions

  • pml_partID (int) – PID for the PML elements

fem.mesh.bc.assign_edge_sym_constraints(bcdict, snic, axes, edge_constraints)

modify/create node BCs for quarter-symmetry edge

Parameters:
  • bcdict – dict of nodal BCs

  • snic – sorted node IDs and coordinates

  • axes – spatial axis vectors

  • edge_constraints – list with vector indicating edge & constraint

  • xmax ((e.g., to specify the edge shared by the) –

  • translation (and ymin faces to allow just z) –

  • ( ((0,1),(1,0),(0,0)),'1,1,0,1,1,1') –

Returns:

bcdict (updated from face assignment)

fem.mesh.bc.assign_node_constraints(snic, axes, face_constraints)

assign node constraints to prescribed node planes

Nodes shared on multiple faces have are assigned with the following order of precedence: z, y, x

Parameters:
  • snic – sorted node IDs and coordinates from nodes.dyn

  • axes – mesh axes [x, y, z]

  • face_constraints – list of DOF strings ordered by

  • ( (xmin, max), (ymin, ...) –

  • (e.g., (('1,1,1,1,1,1' , '0,1,0,0,1,0'),...) –

Returns:

bcdict - dictionary of node BC to be written to bc.dyn

fem.mesh.bc.assign_pml_elems(sorted_elems, pml_elems, pml_partID='2')

assign PML elements in the sorted element matrix

Parameters:
  • sorted_elems – sorted element matrix

  • pml_elems – list of tuples of # PML elems on each axis edge

  • ...) (([[xmin, max], [ymin, ymax],) –

  • pml_partID – default = 2

Returns:

sorted_elems (to be written to new file)

fem.mesh.bc.constrain_sym_pml_nodes(bcdict, snic, axes, pml_elems, edge_constraints)

make sure that all “side” nodes for the PML elements are fully constrained, instead of being assigned the symmetry constraints

THIS FUNCTION IS NOT NEEDED!!

Parameters:
  • bcdict – param snic:

  • axes – param pml_elems:

  • edge_constraints – return: bcdict

  • snic

  • pml_elems

Returns:

bcdict

fem.mesh.bc.main()

apply prescribed boundary conditions to nodes/face segments

fem.mesh.bc.read_cli()

read command line arguments

Args:

Returns:

opts (argparse object)

fem.mesh.bc.writeSeg(BCFILE, title, segID, planeNodeIDs)

write face segments to BC input file

Parameters:
  • BCFILE – file IO object

  • title (str) – header comment line

  • segID (int) – segment ID #

  • planeNodeIDs (int) – 2D array

Returns:

segID (inc +1)

fem.mesh.bc.write_bc(bcdict, bc='bc.dyn')

write node BCs

Parameters:
  • bcdict – dict of node BCs, with DOF values

  • bc – (Default value = “bc.dyn”)

Returns:

0

fem.mesh.bc.write_nonreflecting(BCFILE, segID)

write non-reflecting boundaries (set segments) to input file with segments

This function assumes that segment file has already been written to and not terminated with *END.

Parameters:
  • BCFILE – file IO object

  • segID (int) – maximum segment ID #, assuming started at 1

Returns:

0 on success

fem.mesh.bc.write_pml_elems(sorted_pml_elems, pmlfile='elems_pml.dyn')

Create a new elements file that the PML elements.

Parameters:
  • sorted_pml_elems – param pmlfile: default = elems_pml.dyn

  • pmlfile – (Default value = “elems_pml.dyn”)

Returns:

fem.mesh.create_pointloads_vtk module

create_pointloads_vtk.py

Creates .vts file, which can be viewed in Paraview, from node and point loads files.

Here is one solution I found for viewing the loads on the inside of the mesh: 1. Load the mesh into Paraview.

2. Press the “Calculator” button on the top left side of Paraview. The calculator filter should open up in the sidebar on the left. Next, in the text box between “Result Array Name” and above all of the calculator buttons, type “mag(loads)” without the quotation marks. Next, change the “Result Array Name” from “Result” to something like “load magnitude”. Now, hit the Apply button. This part needs to be done because when the .vts file was created, the loads data were represented as vectors with non-zero values for the z-components only. Taking the magnitude of the loads vectors converts them all into scalar values.

3. Now that we have the loads data in scalar form, we can apply a Threshold filter to visualize only the nodes with non-zero load values. The Threshold filter can be found on the top left, several buttons to the left of the “Calculator” button. Before applying the Threshold filter, make sure that you are filtering by “load magnitude” and that the lower threshold is a small non-zero value, like 0.000001. You should now only see the nodes with non-zero load values.

4. In order to visualize these nodes within the context of the mesh, you should hit the eye-shaped button next to the .vts file in the side bar to allow the entire mesh to appear in the scene. Next, select the .vts file, scroll down to Opacity in the Properties tab of the sidebar, and change the opacity to around 0.5. You should now be able to see the loads that were previously hidden inside the mesh.

fem.mesh.create_pointloads_vtk.create_vts(args)

Writes .vts file from node and load files. StructuredGrid format assumes a linear mesh, so if your mesh is actually non-plaid, this script should be run using with an elements file.

Parameters:

args

Returns:

fem.mesh.create_pointloads_vtk.create_vtu(args)
Parameters:

args

Returns:

fem.mesh.create_pointloads_vtk.main()
fem.mesh.create_pointloads_vtk.parse_cli()

parse command-line interface arguments

fem.mesh.create_pointloads_vtk.writeCellData(loadout, args)

writes cell part IDs

Parameters:
  • loadout

  • args

Returns:

fem.mesh.create_pointloads_vtk.writeCells(loadout, args)

writes cell connectivity and types to loadout file

Parameters:
  • loadout

  • args

Returns:

fem.mesh.create_pointloads_vtk.writeNodeIDs(loadout, args, numNodes)

writes node IDs to loadout file

Parameters:
  • loadout

  • args

  • numNodes

Returns:

fem.mesh.create_pointloads_vtk.writeNodePositions(loadout, args, filetype)

writes opening tags as well as node positions to loadout file. returns array containing number of nodes (index = 0) and number of elements (index = 1).

Parameters:
  • loadout

  • args

  • filetype

Returns:

fem.mesh.create_pointloads_vtk.writePointLoads(loadout, args, numNodes)

writes point loads to loadout file

Parameters:
  • loadout

  • args

  • numNodes

Returns:

fem.mesh.fem_mesh module

fem_mesh.py - ubiquitous functions for many meshing operations

fem.mesh.fem_mesh.SortElems(elems, axes)

spatially sort node IDs into 3D matrix

Parameters:
  • elems (ndarray) – element definitions, as read from elems.dyn

  • axes (list) – lists of x, y, z axis positions

Returns:

sorted_elems (ndarray)

fem.mesh.fem_mesh.SortNodeIDs(nic, sort=False)

spatially sort node IDs into 3D matrix

Parameters:
  • nic (ndarray) – nodeIDcoords [# nodes x 4, dtype = i4,f4,f4,f4]

  • sort (Boolean) – False (assume node ordering) True (spatially sort)

Returns:

n matrix (x,y,z), axes

Return type:

[snic, axes] (ndarray)

fem.mesh.fem_mesh.count_header_comment_skips(nodefile: str)

count comments lines to skip before the first keyword (*)

Parameters:

nodefile – node keyword filename

Raises:

FileNotFoundError – Cannot open the specified node file.

Returns:

number of comment lines before first keyword

Return type:

count (int)

fem.mesh.fem_mesh.extractPlane(snic, axes, plane)

extract plane node IDs

Extract the node IDs on a specified plane from a sorted node ID & coordinate 3D array.

Parameters:
  • snic (ndarray) – sorted node IDs & coordinates array

  • axes (list) – list of unique coordinates in the x, y, and z dimensions

  • plane (list) – indices of the plane to extract (x=0, y=1, z=2)

Raises:

IndexError – specified plane index does not exist

Returns:

planeNodeIDs (spatially-sorted 2D node IDs on specified plane)

Examples

planeNodeIDs = extractPlane(snic,axes,(0,-0.1))

fem.mesh.fem_mesh.load_elems(elefile: str = 'elems.dyn')

load element definitions

Parameters:

elefile (str) – ‘elems.dyn’

Returns:

elems (ndarray)

fem.mesh.fem_mesh.load_nodeIDs_coords(nodefile: str = 'nodes.dyn')

load in node IDs and coordinates

Exclude ‘*’ keyword lines.

Parameters:

nodefile (str) – ‘nodes.dyn’

Returns:

nodeIDcoords (ndarray)

fem.mesh.fem_mesh.rm_tmp_file(nodefile_nocmt: str)

remove temporary pytest nodefile

Parameters:

nodefile_nocmt (str) – pytest temporary nodefile

Raises:

OSError – cannot remove temporary pytest nodefile

Returns:

None

fem.mesh.fem_mesh.strip_comments(nodefile: str) str

string comment lines starting with $

Parameters:

nodefile – keyword filename

Returns:

nodefile stripped of comments

Return type:

nodefile_nocmt (str)

fem.mesh.parseElemsNodes module

fem.mesh.parseElemsNodes.main()

Module contents