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 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 extract_top_plane_nodes(nodefile, top_face): """ Args: nodefile: param top_face: top_face: Returns: planeNodeIDs """ import numpy as np 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", legacynodes=False, plane_pos: float = 0.0, plane_orientation: int = 0, specific_times: Optional[list] = None): """helper function to run high-level, 2D plane extraction look at using extract3Darfidata to get full, 3D datasets exported (e.g., to view in Paraview) Args: dynadeck (str): main dyna input deck disp_comp (int): component of displacement to extract disp_scale (float): displacement scaling ressim (str): result filename to write nodedyn (str): node defintion input filename dispout (str): binary displacement input filename legacynodes (Boolean): node IDs written with each timestep in dispout plane_pos (float): position of the plane to extract (in the specified plane_orientation) plane_orientation (int): orientation plane to extract from (0 = elev, 1 = lateral, 2 = axial) specific_times (list): optional list of specific time indices to extract """ import sys from pathlib import Path meshPath = Path(__file__).parents[1] / "mesh" sys.path.insert(0, str(meshPath)) import fem_mesh try: plane_pos except NameError: plane_pos = ele_pos node_id_coords = fem_mesh.load_nodeIDs_coords(nodedyn) [snic, axes] = fem_mesh.SortNodeIDs(node_id_coords) image_plane = extract_image_plane(snic, axes, plane_pos, plane_orientation) header = read_header(dispout) if specific_times is None: t = __gen_t(extract_dt(dynadeck), header['num_timesteps']) else: t = __gen_t(extract_dt(dynadeck), specific_times) arfidata = extract_arfi_data(dispout, header, image_plane, disp_comp, disp_scale, legacynodes, specific_times) axis_scale = (-10, 10, -10) save_res_sim(ressim, arfidata, axes, t, axis_scale, plane_pos, plane_orientation) return 0
def extract3Darfidata(dynadeck="dynadeck.dyn", disp_comp=2, disp_scale=-1e4, ressim="res_sim.h5", nodedyn="nodes.dyn", dispout="disp.dat", specific_times=None): """Extract 3D volume of specified displacement component. Args: dynadeck (str): LS-DYNA3D input deck (used to get dt) disp_comp (int): displacement component to extract (0, 1, 2) disp_scale (float): displacement scaling factor (cm -> um) ressim (str): output file name [.mat, .h5, .pvd] nodedyn (str): node input file dispout (str): binary displacement data specific_times (list): optional list of specific time indices """ import sys from pathlib import Path meshPath = Path(__file__).parents[1] / "mesh" sys.path.insert(0, str(meshPath)) import fem_mesh if not ressim.endswith(('.mat', '.h5', '.pvd')): raise NameError('Output res_sim filename not supported') node_id_coords = fem_mesh.load_nodeIDs_coords(nodedyn) [snic, axes] = fem_mesh.SortNodeIDs(node_id_coords) header = read_header(dispout) if specific_times is None: t = __gen_t(extract_dt(dynadeck), header['num_timesteps']) else: t = __gen_t(extract_dt(dynadeck), specific_times) arfidata = extract_arfi_data(dispout, header, snic['id'], disp_comp, disp_scale, legacynodes=False, specific_times=specific_times) save_res_sim(ressim, arfidata, axes, t)
def apply_nonreflect(face_constraints, edge_constraints, nodefile="nodes.dyn", elefile="elems.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' elefile (str): default - 'elems.dyn' bcfile (str): default - 'bc.dyn' segfile (str): default - 'nonreflect_segs.dyn' Returns: 0 on success """ import 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 run(dynadeck, disp_comp=2, disp_scale=-1e4, ressim="res_sim.mat", nodedyn="nodes.dyn", dispout="disp.dat", legacynodes=False): """helper function to run high-level, 2D plane extraction look at using extract3Darfidata to get full, 3D datasets exported (e.g., to view in Paraview) Args: dynadeck (str): main dyna input deck disp_comp (int): component of displacement to extract disp_scale (float): displacement scaling ressim (str): result filename to write nodedyn (str): node defintion input filename dispout (str): binary displacement input filename legacynodes (Boolean): node IDs written with each timestep in dispout """ import sys from pathlib import Path meshPath = Path(__file__).parents[1] / "mesh" sys.path.insert(0, str(meshPath)) 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) t = __gen_t(extract_dt(dynadeck), header['num_timesteps']) arfidata = extract_arfi_data(dispout, header, image_plane, disp_comp, disp_scale, legacynodes) save_res_sim(ressim, arfidata, axes, t) return 0
def extract3Darfidata(dynadeck=None, disp_comp=2, disp_scale=-1e4, ressim="res_sim.h5", nodedyn="nodes.dyn", dispout="disp.dat"): """Extract 3D volume of specified displacement component. Args: dynadeck (str): LS-DYNA3D input deck (used to get dt) disp_comp (int): displacement component to extract (0, 1, 2) disp_scale (float): displacement scaling factor (cm -> um) ressim (str): output file name [.mat, .h5, .pvd] nodedyn (str): node input file dispout (str): binary displacement data """ import os import sys myPath = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, myPath + '/../mesh/') import fem_mesh import numpy as np if not ressim.endswith(('.mat', '.h5', '.pvd')): raise NameError('Output res_sim filename not supported') node_id_coords = fem_mesh.load_nodeIDs_coords(nodedyn) [snic, axes] = fem_mesh.SortNodeIDs(node_id_coords) 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, snic['id'], disp_comp, disp_scale, legacynodes=False) save_res_sim(ressim, arfidata, axes, t)
def run(dynadeck, disp_comp=2, disp_scale=-1e4, ressim="res_sim.mat", nodedyn="nodes.dyn", dispout="disp.dat", legacynodes=False): """ Args: dynadeck (str): main dyna input deck disp_comp (int): component of displacement to extract disp_scale (float): displacement scaling ressim (str): result filename to write nodedyn (str): node defintion input filename dispout (str): binary displacement input filename legacynodes (Boolean): node IDs written with each timestep in dispout """ import os import sys myPath = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, myPath + '/../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) t = gen_t(extract_dt(dynadeck), header['num_timesteps']) arfidata = extract_arfi_data(dispout, header, image_plane, disp_comp, disp_scale, legacynodes) save_res_sim(ressim, arfidata, axes, t) return 0
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 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 main(): import fem_mesh import sys fem_mesh.check_version() opts = read_cli() BCFILE = open_bcfile(opts, sys.argv[0]) nodeIDcoords = load_nodeIDs_coords(opts.nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) segID = 1 # BACK plane = (0, axes[0].min()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) segID = writeSeg(BCFILE, 'BACK', segID, planeNodeIDs) # FRONT plane = (0, axes[0].max()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) if (opts.sym == 'q') or (opts.sym == 'h'): # no top / bottom rows (those will be defined in the # top/bottom defs) writeNodeBC(BCFILE, planeNodeIDs[1:-1], '1,0,0,0,1,1') else: segID = writeSeg(BCFILE, 'FRONT', segID, planeNodeIDs) # LEFT (push side; non-reflecting or symmetry) plane = (1, axes[1].min()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) # if quarter-symmetry, then apply BCs, in addition to a # modified edge; and don't deal w/ top/bottom if opts.sym == 'q': writeNodeBC(BCFILE, planeNodeIDs[1:-1], '0,1,0,1,0,1') # else make it a non-reflecting boundary else: segID = writeSeg(BCFILE, 'LEFT', segID, planeNodeIDs) # RIGHT (non-reflecting) plane = (1, axes[1].max()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) segID = writeSeg(BCFILE, 'RIGHT', segID, planeNodeIDs) # BOTTOM plane = (2, axes[2].min()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) segID = writeSeg(BCFILE, 'BOTTOM', segID, planeNodeIDs) if opts.bottom == 'full': writeNodeBC(BCFILE, planeNodeIDs, '1,1,1,1,1,1') elif opts.bottom == 'inplane': writeNodeBC(BCFILE, planeNodeIDs, '0,0,1,1,1,0') # TOP (transducer face) plane = (2, axes[2].max()) planeNodeIDs = fem_mesh.extractPlane(snic, axes, plane) segID = writeSeg(BCFILE, 'TOP', segID, planeNodeIDs) if opts.top: writeNodeBC(BCFILE, planeNodeIDs, '1,1,1,1,1,1') write_nonreflecting(BCFILE, segID) BCFILE.close()
def main(): import fem_mesh import sys fem_mesh.check_version() opts = read_cli() if opts.pml: pmlfile = create_pml_elems_file(opts.elefile) BCFILE = open_bcfile(opts, sys.argv[0]) nodeIDcoords = load_nodeIDs_coords(opts.nodefile) [snic, axes] = fem_mesh.SortNodeIDs(nodeIDcoords) axdiff = [ axes[0][1] - axes[0][0], axes[1][1] - axes[1][0], axes[2][1] - axes[2][0] ] segID = 1 # BACK axis = 0 axis_limit = axes[0].min() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) if opts.nonreflect: segID = writeSeg(BCFILE, 'BACK', segID, planeNodeIDs) elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit, axis_limit + opts.num_pml_elems * axdiff[axis], opts.pml_partID) # FRONT axis = 0 axis_limit = axes[0].max() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) if (opts.sym == 'q') or (opts.sym == 'h'): # no top / bottom rows (those will be defined in the # top/bottom defs) writeNodeBC(BCFILE, planeNodeIDs[1:-1], '1,0,0,0,1,1') else: if opts.nonreflect: segID = writeSeg(BCFILE, 'FRONT', segID, planeNodeIDs) elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit - opts.num_pml_elems * axdiff[axis], axis_limit, opts.pml_partID) # LEFT (push side; non-reflecting or symmetry) axis = 1 axis_limit = axes[1].min() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) # if quarter-symmetry, then apply BCs, in addition to a # modified edge; and don't deal w/ top/bottom if opts.sym == 'q': writeNodeBC(BCFILE, planeNodeIDs[1:-1], '0,1,0,1,0,1') # else make it a non-reflecting boundary else: if opts.nonreflect: segID = writeSeg(BCFILE, 'LEFT', segID, planeNodeIDs) elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit, axis_limit + opts.num_pml_elems * axdiff[axis], opts.pml_partID) # RIGHT (non-reflecting) axis = 1 axis_limit = axes[1].max() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) if opts.nonreflect: segID = writeSeg(BCFILE, 'RIGHT', segID, planeNodeIDs) elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit - opts.num_pml_elems * axdiff[axis], axis_limit, opts.pml_partID) # BOTTOM axis = 2 axis_limit = axes[2].min() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) if opts.nonreflect: segID = writeSeg(BCFILE, 'BOTTOM', segID, planeNodeIDs) if opts.bottom == 'full': writeNodeBC(BCFILE, planeNodeIDs, '1,1,1,1,1,1') elif opts.bottom == 'inplane': writeNodeBC(BCFILE, planeNodeIDs, '0,0,1,1,1,0') elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit, axis_limit + opts.num_pml_elems * axdiff[axis], opts.pml_partID) # TOP (transducer face) axis = 2 axis_limit = axes[2].max() planeNodeIDs = fem_mesh.extractPlane(snic, axes, (axis, axis_limit)) if opts.nonreflect: segID = writeSeg(BCFILE, 'TOP', segID, planeNodeIDs) if opts.top: writeNodeBC(BCFILE, planeNodeIDs, '1,1,1,1,1,1') elif opts.pml: apply_pml(opts.nodefile, pmlfile, BCFILE, planeNodeIDs, axis, axis_limit - opts.num_pml_elems * axdiff[axis], axis_limit, opts.pml_partID) if opts.nonreflect: write_nonreflecting(BCFILE, segID) BCFILE.close()