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()¶