def extract_top_plane_nodes(nodefile, top_face): """ Args: nodefile: param top_face: top_face: Returns: planeNodeIDs """ import numpy as np from fem.mesh import fem_mesh top_face = np.array(top_face) nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) # extract spatially-sorted node IDs on a the top z plane axis = int(np.floor(np.divide(top_face.nonzero(), 2))) if np.mod(top_face.nonzero(), 2) == 1: plane = (axis, axes[axis].max()) else: plane = (axis, axes[axis].min()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) return planeNodeIDs
def run(dynadeck, disp_comp=2, disp_scale=-1e4, ressim="res_sim.mat", nodedyn="nodes.dyn", dispout="disp.dat.xz", legacynodes=False): """ :param dynadeck: main dyna input deck :param disp_comp=2: component of displacement to extract :param disp_scale=-1e4: displacement scaling :param ressim: default = "res_sim.mat" :param nodedyn: default = "nodes.dyn" :param dispout: default = "disp.dat.xz" :return: 0 """ from fem.mesh import fem_mesh node_id_coords = fem_mesh.load_nodeIDs_coords(nodedyn) [snic, axes] = fem_mesh.SortNodeIDs(node_id_coords) image_plane = extract_image_plane(snic, axes, ele_pos=0.0) header = read_header(dispout) dt = extract_dt(dynadeck) t = [float(x) * dt for x in range(0, header['num_timesteps'])] arfidata = extract_arfi_data(dispout, header, image_plane, disp_comp, disp_scale, legacynodes) save_res_mat(ressim, arfidata, axes, t) return 0
def test_extract_arfi_data(): """test extraction of arfi data at specific timesteps """ from fem.post.create_res_sim import extract_arfi_data from fem.post.create_res_sim import read_header from fem.post.create_res_sim import extract_image_plane from fem.mesh.fem_mesh import load_nodeIDs_coords from fem.mesh.fem_mesh import SortNodeIDs from scipy.io import loadmat import numpy as np gauss_qsym_pml_example_path = examplesPath / "gauss_qsym_pml" dispout = gauss_qsym_pml_example_path / "disp.dat.xz" nodedyn = gauss_qsym_pml_example_path / "nodes.dyn" valid_data = loadmat(gauss_qsym_pml_example_path / "res_sim_valid.mat")['arfidata'] header = read_header(dispout) node_id_coords = load_nodeIDs_coords(nodedyn) [snic, axes] = SortNodeIDs(node_id_coords) image_plane = extract_image_plane(snic, axes) test_data0 = extract_arfi_data(dispout, header, image_plane) test_data1 = extract_arfi_data(dispout, header, image_plane, specific_times=[1, 3]) test_data2 = extract_arfi_data(dispout, header, image_plane, specific_times=[3, 2, 1]) assert np.array_equal(test_data0, valid_data) assert np.array_equal(test_data1, valid_data[:, :, [0, 2]]) assert np.array_equal(test_data2, np.flip(valid_data, axis=-1))
def nodeIDcoords(): """create node ID and coordinate matrix from nodes.dyn :returns: [snic, axes] """ from fem.mesh.fem_mesh import load_nodeIDs_coords nodeIDcoords = load_nodeIDs_coords(testPath / "nodes.dyn") return nodeIDcoords
def extract3Darfidata(dynadeck, disp_comp=2, disp_scale=-1e4, ressim="res_sim.h5", nodedyn="nodes.dyn", dispout="disp.dat.xz"): from fem.mesh import fem_mesh import fem.post.create_res_sim_mat as crsm import numpy as np node_id_coords = fem_mesh.load_nodeIDs_coords(nodedyn) [snic, axes] = fem_mesh.SortNodeIDs(node_id_coords) header = crsm.read_header(dispout) dt = crsm.extract_dt(dynadeck) t = [float(x) * dt for x in range(0, header['num_timesteps'])] arfidata = crsm.extract_arfi_data(dispout, header, snic['id'], disp_comp, disp_scale, legacynodes=False) crsm.save_res_mat(ressim, arfidata, axes, t)
def apply_nonreflect(face_constraints, edge_constraints, nodefile="nodes.dyn", bcfile="bc.dyn", segfile="nonreflect_segs.dyn"): """driver function to generate non-reflecting boundaries Args: 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 """ import fem.mesh.fem_mesh as fem_mesh nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) segID = 1 seg_names = [['XMIN', 'XMAX'], ['YMIN', 'YMAX'], ['ZMIN', 'ZMAX']] SEGBCFILE = open(segfile, 'w') for a in range(0, 3): for m in range(0, 2): if face_constraints[a][m] == '1,1,1,1,1,1': if m == 0: axis_limit = axes[a][0] else: axis_limit = axes[a][-1] planeNodeIDs = fem_mesh.extractPlane(snic, axes, (a, axis_limit)) segID = writeSeg(SEGBCFILE, seg_names[a][m], segID, planeNodeIDs) write_nonreflecting(SEGBCFILE, segID) SEGBCFILE.close() bcdict = assign_node_constraints(snic, axes, face_constraints) bcdict = assign_edge_sym_constraints(bcdict, snic, axes, edge_constraints) write_bc(bcdict, bcfile) return 0
def apply_face_bc_only(face_constraints, nodefile="nodes.dyn", bcfile="bc.dyn"): """driver function to apply node BCs just to faces :param face_constraints: 3x2 array of strings, specifying the BCs on each face (3), min/max (2) :param nodefile: default - 'nodes.dyn' :param bcfile: 'defauly - 'bc.dyn' :return: """ from fem.mesh import fem_mesh nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) bcdict = assign_node_constraints(snic, axes, face_constraints) write_bc(bcdict, bcfile) return 0
def 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 :param pml_elems: 3x2 array of ints specifying thickness of PML elements (5--10) on each PML layer :param face_constraints: 3x2 array of strings, specifying the BCs on each face (3), min/max (2) :param edge_constraints: 1x6 vector of BCs on each edge :param nodefile: default - 'nodes.dyn' :param elefile: default - 'elems.dyn' :param pmlfile: default - 'elems_pml.dyn' :param bcfile: 'defauly - 'bc.dyn' :param pml_partID: default - 2 :return: """ from fem.mesh import fem_mesh nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) elems = fem_mesh.load_elems(elefile) sorted_elems = fem_mesh.SortElems(elems, axes) sorted_pml_elems = assign_pml_elems(sorted_elems, pml_elems, pml_partID) write_pml_elems(sorted_pml_elems, pmlfile) bcdict = assign_node_constraints(snic, axes, face_constraints) bcdict = constrain_sym_pml_nodes(bcdict, snic, axes, pml_elems, edge_constraints) bcdict = assign_edge_sym_constraints(bcdict, snic, axes, edge_constraints) write_bc(bcdict, bcfile) return 0
def 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 Args: 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 """ import fem.mesh.fem_mesh as fem_mesh nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) elems = fem_mesh.load_elems(elefile) sorted_elems = fem_mesh.SortElems(elems, axes) sorted_pml_elems = assign_pml_elems(sorted_elems, pml_elems, pml_partID) write_pml_elems(sorted_pml_elems, pmlfile) bcdict = assign_node_constraints(snic, axes, face_constraints) bcdict = constrain_sym_pml_nodes(bcdict, snic, axes, pml_elems, edge_constraints) bcdict = assign_edge_sym_constraints(bcdict, snic, axes, edge_constraints) write_bc(bcdict, bcfile)
def apply_face_bc_only(face_constraints, nodefile="nodes.dyn", bcfile="bc.dyn"): """Driver function to apply node BCs just to faces. Args: 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) """ import fem.mesh.fem_mesh as fem_mesh nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) bcdict = assign_node_constraints(snic, axes, face_constraints) write_bc(bcdict, bcfile)
def findStructNodeIDs(nodefile, struct_type, sopts): """find nodes in given geometry Find node IDs that fall within a specified geometry (sphere, layer, cube, ellipsoid). :param str nodefile: (default: nodes.dyn) :param str struct_type: sphere, layer, ellipsoid, cube :param sopts: struct-specific parameters :returns: structNodeIDs (dict) """ import sys import numpy as n import math as m from fem.mesh import fem_mesh header_comment_skips = fem_mesh.count_header_comment_skips(nodefile) nodeIDcoords = fem_mesh.load_nodeIDs_coords(nodefile) structNodeIDs = {} # TODO: replace sopts approach; figure out something more robust if struct_type is 'sphere': """ sopts is assumed to be a 4 element tuple with the following items: sphere center coordinates (x,y,z) sphere radius """ for i in nodeIDcoords: nodeRad = n.sqrt( n.power((i[1] - sopts[0]), 2) + n.power((i[2] - sopts[1]), 2) + n.power((i[3] - sopts[2]), 2)) if nodeRad < sopts[3]: structNodeIDs[i[0]] = True elif struct_type is 'layer': """ sopts is assumed to be a 3 element tuple with the following items: dimension for normal to layer (x = 1, y = 2, z = 3) layer bounds (min,max) """ for i in nodeIDcoords: if i[sopts[0]] > sopts[1] and i[sopts[0]] < sopts[2]: structNodeIDs[i[0]] = True elif struct_type is 'ellipsoid': """ sopts is assumed to be a 9 element tuple with the following items: ellipsoid center coordinates (x,y,z) ellipsoid half-axis lengths (a,b,c) ellipsoid euler angles (phi,theta,psi) in DEGREES """ cph = m.cos(m.radians(sopts[6])) # cos(phi) sph = m.sin(m.radians(sopts[6])) # sin(phi) cth = m.cos(m.radians(sopts[7])) # cos(theta) sth = m.sin(m.radians(sopts[7])) # sin(theta) cps = m.cos(m.radians(sopts[8])) # cos(psi) sps = m.sin(m.radians(sopts[8])) # sin(psi) # rotation matrix R = n.matrix([[ cth * cps, -cph * sps + sph * sth * cps, sph * sps + cph * sth * cps ], [ cth * sps, cph * cps + sph * sth * sps, -sph * cps + cph * sth * sps ], [-sth, sph * cth, cph * cth]]) # diagonal maxtrix of squared ellipsoid half-axis lengths A = n.matrix([[n.power(sopts[3], 2), 0, 0], [0, n.power(sopts[4], 2), 0], [0, 0, n.power(sopts[5], 2)]]) # A matrix - eigenvalues are a^2,b^2,c^2 (square of half-axis lengths), # eigenvectors are directions of the orthogonal principal axes A = R.transpose().dot(A).dot(R) # locate nodes within ellipsoid for i in nodeIDcoords: radVec = n.matrix([[i[1] - sopts[0]], [i[2] - sopts[1]], [i[3] - sopts[2]]]) if radVec.transpose().dot(A.I).dot(radVec) <= 1: structNodeIDs[i[0]] = True elif struct_type is 'cube': """ sopts is assumed to be a 6 element tuple with the following items: Location of most-negative corner (x,y,z) Respective cube dimensions (x,y,z) """ for i in nodeIDcoords: if i[1] >= sopts[0] and \ i[1] <= (sopts[0] + sopts[3]) and \ i[2] >= sopts[1] and \ i[2] <= (sopts[1] + sopts[4]) and \ i[3] >= sopts[2] and \ i[3] <= (sopts[2] + sopts[5]): structNodeIDs[i[0]] = True else: sys.exit('ERROR: The specified structure is not defined') if len(structNodeIDs) == 0: sys.exit('ERROR: no structure nodes were found') return structNodeIDs
def load_sorted_nodes(self): """ """ from fem.mesh import fem_mesh nic = fem_mesh.load_nodeIDs_coords(nodefile=self.nodefile) [self.snic, self.axes] = fem_mesh.SortNodeIDs(nic)