def savevtk(name, mesh): """ SAVEVTK: save a JIGSAW MSH object to file. SAVEVTK(NAME, MESH) MESH is JIGSAW's primary mesh/grid/geom class. See MSH_t for details. Data in MESH is written as-needed -- any objects defined will be saved to file. """ if (not isinstance(name, str)): raise Exception("Incorrect type: NAME.") if (not isinstance(mesh, jigsaw_msh_t)): raise Exception("Incorrect type: MESH.") certify(mesh) fext = Path(name).suffix if (fext.strip() != ".vtk"): name = name + ".vtk" kind = mesh.mshID.lower() with Path(name).open("w") as fptr: #----------------------------------- write JIGSAW object if (kind == "euclidean-mesh"): save_mesh_file(mesh, fptr) elif (kind == "ellipsoid-mesh"): save_mesh_file(mesh, fptr) elif (kind == "euclidean-grid"): save_grid_file(mesh, fptr) elif (kind == "ellipsoid-grid"): save_grid_file(mesh, fptr) else: raise Exception("MESH.mshID is not supported!!") return
def savemsh(name, mesh): """ SAVEMSH: save a JIGSAW MSH object to file. SAVEMSH(NAME, MESH) MESH is JIGSAW's primary mesh/grid/geom class. See MSH_t for details. Data in MESH is written as-needed -- any objects defined will be saved to file. """ if (not isinstance(name, str)): raise Exception("Incorrect type: NAME.") if (not isinstance(mesh, jigsaw_msh_t)): raise Exception("Incorrect type: MESH.") nver = +3 certify(mesh) fext = Path(name).suffix if (fext.strip() != ".msh"): name = name + ".msh" kind = mesh.mshID.lower() with Path(name).open("w") as fptr: #----------------------------------- write JIGSAW object fptr.write("# " + Path(name).name + "; created by JIGSAW's PYTHON interface \n") if (kind == "euclidean-mesh"): save_mesh_file(mesh, fptr, nver, "euclidean-mesh") if (kind == "euclidean-grid"): save_grid_file(mesh, fptr, nver, "euclidean-grid") if (kind == "ellipsoid-mesh"): save_mesh_file(mesh, fptr, nver, "ellipsoid-mesh") if (kind == "ellipsoid-grid"): save_grid_file(mesh, fptr, nver, "ellipsoid-grid") return
def put_msh_t(msht, mshl): """ PUT-MSH_t: Assign ptrs from python-to-ctypes objects. """ if (msht is None): return certify(msht) if (msht.mshID is not None): #--------------------------------- assign mshID variable istr = msht.mshID.lower() if (istr == "euclidean-mesh"): mshl.flags = \ defs.JIGSAW_EUCLIDEAN_MESH if (istr == "euclidean-grid"): mshl.flags = \ defs.JIGSAW_EUCLIDEAN_GRID if (istr == "ellipsoid-mesh"): mshl.flags = \ defs.JIGSAW_ELLIPSOID_MESH if (istr == "ellipsoid-grid"): mshl.flags = \ defs.JIGSAW_ELLIPSOID_GRID if (msht.radii is not None and msht.radii.size != +0): #--------------------------------- assign ptrs for RADII mshl.radii.size = msht.radii.size mshl.radii.data = \ put_ptr_t(msht.radii, real_t) if (msht.vert2 is not None and msht.vert2.size != +0): #--------------------------------- assign ptrs for VERT2 mshl.vert2.size = msht.vert2.size mshl.vert2.data = put_ptr_t(msht.vert2, libsaw_VERT2_t) if (msht.vert3 is not None and msht.vert3.size != +0): #--------------------------------- assign ptrs for VERT3 mshl.vert3.size = msht.vert3.size mshl.vert3.data = put_ptr_t(msht.vert3, libsaw_VERT3_t) if (msht.power is not None and msht.power.size != +0): #--------------------------------- assign ptrs for POWER mshl.power.size = msht.power.size mshl.power.data = \ put_ptr_t(msht.power, real_t) if (msht.edge2 is not None and msht.edge2.size != +0): #--------------------------------- assign ptrs for EDGE2 mshl.edge2.size = msht.edge2.size mshl.edge2.data = put_ptr_t(msht.edge2, libsaw_EDGE2_t) if (msht.tria3 is not None and msht.tria3.size != +0): #--------------------------------- assign ptrs for TRIA3 mshl.tria3.size = msht.tria3.size mshl.tria3.data = put_ptr_t(msht.tria3, libsaw_TRIA3_t) if (msht.quad4 is not None and msht.quad4.size != +0): #--------------------------------- assign ptrs for QUAD4 mshl.quad4.size = msht.quad4.size mshl.quad4.data = put_ptr_t(msht.quad4, libsaw_QUAD4_t) if (msht.tria4 is not None and msht.tria4.size != +0): #--------------------------------- assign ptrs for TRIA4 mshl.tria4.size = msht.tria4.size mshl.tria4.data = put_ptr_t(msht.tria4, libsaw_TRIA4_t) if (msht.hexa8 is not None and msht.hexa8.size != +0): #--------------------------------- assign ptrs for HEXA8 mshl.hexa8.size = msht.hexa8.size mshl.hexa8.data = put_ptr_t(msht.hexa8, libsaw_HEXA8_t) if (msht.wedg6 is not None and msht.wedg6.size != +0): #--------------------------------- assign ptrs for WEDG6 mshl.wedg6.size = msht.wedg6.size mshl.wedg6.data = put_ptr_t(msht.wedg6, libsaw_WEDG6_t) if (msht.pyra5 is not None and msht.pyra5.size != +0): #--------------------------------- assign ptrs for PYRA5 mshl.pyra5.size = msht.pyra5.size mshl.pyra5.data = put_ptr_t(msht.pyra5, libsaw_PYRA5_t) if (msht.bound is not None and msht.bound.size != +0): #--------------------------------- assign ptrs for BOUND mshl.bound.size = msht.bound.size mshl.bound.data = put_ptr_t(msht.bound, libsaw_BOUND_t) if (msht.xgrid is not None and msht.xgrid.size != +0): #--------------------------------- assign ptrs for XGRID mshl.xgrid.size = msht.xgrid.size mshl.xgrid.data = \ put_ptr_t(msht.xgrid, real_t) if (msht.ygrid is not None and msht.ygrid.size != +0): #--------------------------------- assign ptrs for YGRID mshl.ygrid.size = msht.ygrid.size mshl.ygrid.data = \ put_ptr_t(msht.ygrid, real_t) if (msht.zgrid is not None and msht.zgrid.size != +0): #--------------------------------- assign ptrs for ZGRID mshl.zgrid.size = msht.zgrid.size mshl.zgrid.data = \ put_ptr_t(msht.zgrid, real_t) if (msht.value is not None and msht.value.size != +0): #--------------------------------- assign ptrs for VALUE mshl.value.size = msht.value.size mshl.value.data = \ put_ptr_t(msht.value, real_t) if (msht.slope is not None and msht.slope.size != +0): #--------------------------------- assign ptrs for SLOPE mshl.slope.size = msht.slope.size mshl.slope.data = \ put_ptr_t(msht.slope, real_t) return
def bisect(mesh): """ BISECT: perform uniform bisection of a mesh object. """ if (not isinstance(mesh, jigsaw_msh_t)): raise Exception("Incorrect type: MESH.") certify(mesh) if (mesh.point is None): return #------------------------------ map elements to unique edges edge = np.empty((0, 2), dtype=np.int32) emap = mapper() quad = np.empty((0, 4), dtype=np.int32) qmap = mapper() hexa = np.empty((0, 8), dtype=np.int32) # hmap = mapper() if (mesh.edge2 is not None and mesh.edge2.size != +0): #-------------------------- map EDGE2's onto JOIN arrays nedg = edge.shape[0] ncel = mesh.edge2.shape[0] cell = mesh.edge2["index"] edge = np.concatenate((edge, cell[:, (0, 1)]), axis=0) indx = np.arange(0, ncel) emap.edge2.index = \ np.empty((ncel, 1), dtype=np.int32) emap.edge2.index[:, 0] = \ indx + ncel * 0 + nedg if (mesh.tria3 is not None and mesh.tria3.size != +0): #-------------------------- map TRIA3's onto JOIN arrays nedg = edge.shape[0] ncel = mesh.tria3.shape[0] cell = mesh.tria3["index"] edge = np.concatenate((edge, cell[:, (0, 1)]), axis=0) edge = np.concatenate((edge, cell[:, (1, 2)]), axis=0) edge = np.concatenate((edge, cell[:, (2, 0)]), axis=0) indx = np.arange(0, ncel) emap.tria3.index = \ np.empty((ncel, 3), dtype=np.int32) emap.tria3.index[:, 0] = \ indx + ncel * 0 + nedg emap.tria3.index[:, 1] = \ indx + ncel * 1 + nedg emap.tria3.index[:, 2] = \ indx + ncel * 2 + nedg if (mesh.quad4 is not None and mesh.quad4.size != +0): #-------------------------- map QUAD4's onto JOIN arrays nedg = edge.shape[0] nfac = quad.shape[0] ncel = mesh.quad4.shape[0] cell = mesh.quad4["index"] quad = np.concatenate((quad, cell[:, +0:+4]), axis=0) edge = np.concatenate((edge, cell[:, (0, 1)]), axis=0) edge = np.concatenate((edge, cell[:, (1, 2)]), axis=0) edge = np.concatenate((edge, cell[:, (2, 3)]), axis=0) edge = np.concatenate((edge, cell[:, (3, 0)]), axis=0) indx = np.arange(0, ncel) qmap.quad4.index = \ np.empty((ncel, 1), dtype=np.int32) qmap.quad4.index[:, 0] = \ indx + ncel * 0 + nfac emap.quad4.index = \ np.empty((ncel, 4), dtype=np.int32) emap.quad4.index[:, 0] = \ indx + ncel * 0 + nedg emap.quad4.index[:, 1] = \ indx + ncel * 1 + nedg emap.quad4.index[:, 2] = \ indx + ncel * 2 + nedg emap.quad4.index[:, 3] = \ indx + ncel * 3 + nedg if (mesh.tria4 is not None and mesh.tria4.size != +0): #-------------------------- map TRIA4's onto JOIN arrays nedg = edge.shape[0] ncel = mesh.tria4.shape[0] cell = mesh.tria4["index"] edge = np.concatenate((edge, cell[:, (0, 1)]), axis=0) edge = np.concatenate((edge, cell[:, (1, 2)]), axis=0) edge = np.concatenate((edge, cell[:, (2, 0)]), axis=0) edge = np.concatenate((edge, cell[:, (0, 3)]), axis=0) edge = np.concatenate((edge, cell[:, (1, 3)]), axis=0) edge = np.concatenate((edge, cell[:, (2, 3)]), axis=0) indx = np.arange(0, ncel) emap.tria4.index = \ np.empty((ncel, 6), dtype=np.int32) emap.tria4.index[:, 0] = \ indx + ncel * 0 + nedg emap.tria4.index[:, 1] = \ indx + ncel * 1 + nedg emap.tria4.index[:, 2] = \ indx + ncel * 2 + nedg emap.tria4.index[:, 3] = \ indx + ncel * 3 + nedg emap.tria4.index[:, 4] = \ indx + ncel * 4 + nedg emap.tria4.index[:, 5] = \ indx + ncel * 5 + nedg if (mesh.hexa8 is not None and mesh.hexa8.size != +0): #-------------------------- map HEXA8's onto JOIN arrays warnings.warn("HEXA8 is not unsupported", Warning) if (mesh.wedg6 is not None and mesh.wedg6.size != +0): #-------------------------- map WEDG6's onto JOIN arrays warnings.warn("WEDG6 is not unsupported", Warning) if (mesh.pyra5 is not None and mesh.pyra5.size != +0): #-------------------------- map PYRA5's onto JOIN arrays warnings.warn("PYRA5 is not unsupported", Warning) #------------------------------ unique joins and re-indexing if (edge.size != 0): __, efwd, erev = np.unique(np.sort(edge, axis=+1), return_index=True, return_inverse=True, axis=0) edge = edge[efwd, :] if (quad.size != 0): __, qfwd, qrev = np.unique(np.sort(quad, axis=+1), return_index=True, return_inverse=True, axis=0) quad = quad[qfwd, :] if (hexa.size != 0): __, hfwd, hrev = np.unique(np.sort(hexa, axis=+1), return_index=True, return_inverse=True, axis=0) hexa = hexa[hfwd, :] #------------------------------ map unique joins to elements if (mesh.edge2 is not None and mesh.edge2.size != +0): emap.edge2.index[:, 0] = \ erev[emap.edge2.index[:, 0]] if (mesh.tria3 is not None and mesh.tria3.size != +0): emap.tria3.index[:, 0] = \ erev[emap.tria3.index[:, 0]] emap.tria3.index[:, 1] = \ erev[emap.tria3.index[:, 1]] emap.tria3.index[:, 2] = \ erev[emap.tria3.index[:, 2]] if (mesh.quad4 is not None and mesh.quad4.size != +0): qmap.quad4.index[:, 0] = \ qrev[emap.quad4.index[:, 0]] emap.quad4.index[:, 0] = \ erev[emap.quad4.index[:, 0]] emap.quad4.index[:, 1] = \ erev[emap.quad4.index[:, 1]] emap.quad4.index[:, 2] = \ erev[emap.quad4.index[:, 2]] emap.quad4.index[:, 3] = \ erev[emap.quad4.index[:, 3]] if (mesh.tria4 is not None and mesh.tria4.size != +0): emap.tria4.index[:, 0] = \ erev[emap.tria4.index[:, 0]] emap.tria4.index[:, 1] = \ erev[emap.tria4.index[:, 1]] emap.tria4.index[:, 2] = \ erev[emap.tria4.index[:, 2]] emap.tria4.index[:, 3] = \ erev[emap.tria4.index[:, 3]] emap.tria4.index[:, 4] = \ erev[emap.tria4.index[:, 4]] emap.tria4.index[:, 5] = \ erev[emap.tria4.index[:, 5]] #------------------------------ create new midpoint vertices enew = np.empty((0), dtype=np.int32) qnew = np.empty((0), dtype=np.int32) hnew = np.empty((0), dtype=np.int32) if (edge.size != +0): #-------------------------- create new vertices for EDGE if (mesh.point is not None and mesh.point.size != +0): vert = mesh.point["coord"] itag = mesh.point["IDtag"] emid = \ vert[edge[:, 0], :] + \ vert[edge[:, 1], :] emid = emid / +2.0 imid = itag[edge[:, 0]] nold = np.size(vert, 0) nnew = np.size(emid, 0) enew = nold + np.arange(+0, nnew) vnew = np.empty(nnew, dtype=mesh.point.dtype) vnew["coord"] = emid vnew["IDtag"] = imid mesh.point = np.concatenate((mesh.point, vnew), axis=0) if (quad.size != +0): #-------------------------- create new vertices for QUAD if (mesh.point is not None and mesh.point.size != +0): vert = mesh.point["coord"] itag = mesh.point["IDtag"] qmid = \ vert[quad[:, 0], :] + \ vert[quad[:, 1], :] + \ vert[quad[:, 2], :] + \ vert[quad[:, 3], :] qmid = qmid / +4.0 imid = itag[quad[:, 0]] nold = np.size(vert, 0) nnew = np.size(qmid, 0) qnew = nold + np.arange(+0, nnew) vnew = np.empty(nnew, dtype=mesh.point.dtype) vnew["coord"] = qmid vnew["IDtag"] = imid mesh.point = np.concatenate((mesh.point, vnew), axis=0) if (hexa.size != +0): #-------------------------- create new vertices for HEXA if (mesh.point is not None and mesh.point.size != +0): vert = mesh.point["coord"] itag = mesh.point["IDtag"] hmid = \ vert[hexa[:, 0], :] + \ vert[hexa[:, 1], :] + \ vert[hexa[:, 2], :] + \ vert[hexa[:, 3], :] + \ vert[hexa[:, 4], :] + \ vert[hexa[:, 5], :] + \ vert[hexa[:, 6], :] + \ vert[hexa[:, 7], :] hmid = hmid / +8.0 imid = itag[hexa[:, 0]] nold = np.size(vert, 0) nnew = np.size(hmid, 0) hnew = nold + np.arange(+0, nnew) vnew = np.empty(nnew, dtype=mesh.point.dtype) vnew["coord"] = hmid vnew["IDtag"] = imid mesh.point = np.concatenate((mesh.point, vnew), axis=0) if (mesh.edge2 is not None and mesh.edge2.size != +0): #------------------------------ create new indexes for EDGE2 node1 = mesh.edge2["index"][:, 0] node2 = mesh.edge2["index"][:, 1] node3 = \ enew[emap.edge2.index[:, 0]] edgeA = np.empty((mesh.edge2.shape[0]), dtype=jigsaw_msh_t.EDGE2_t) edgeA["index"][:, 0] = node1 edgeA["index"][:, 1] = node3 edgeA["IDtag"] = mesh.edge2["IDtag"] edgeB = np.empty((mesh.edge2.shape[0]), dtype=jigsaw_msh_t.EDGE2_t) edgeB["index"][:, 0] = node3 edgeB["index"][:, 1] = node2 edgeB["IDtag"] = mesh.edge2["IDtag"] mesh.edge2 = np.concatenate((edgeA, edgeB), axis=+0) if (mesh.tria3 is not None and mesh.tria3.size != +0): #------------------------------ create new indexes for TRIA3 node1 = mesh.tria3["index"][:, 0] node2 = mesh.tria3["index"][:, 1] node3 = mesh.tria3["index"][:, 2] node4 = \ enew[emap.tria3.index[:, 0]] node5 = \ enew[emap.tria3.index[:, 1]] node6 = \ enew[emap.tria3.index[:, 2]] triaA = np.empty((mesh.tria3.shape[0]), dtype=jigsaw_msh_t.TRIA3_t) triaA["index"][:, 0] = node1 triaA["index"][:, 1] = node4 triaA["index"][:, 2] = node6 triaA["IDtag"] = mesh.tria3["IDtag"] triaB = np.empty((mesh.tria3.shape[0]), dtype=jigsaw_msh_t.TRIA3_t) triaB["index"][:, 0] = node2 triaB["index"][:, 1] = node5 triaB["index"][:, 2] = node4 triaB["IDtag"] = mesh.tria3["IDtag"] triaC = np.empty((mesh.tria3.shape[0]), dtype=jigsaw_msh_t.TRIA3_t) triaC["index"][:, 0] = node3 triaC["index"][:, 1] = node6 triaC["index"][:, 2] = node5 triaC["IDtag"] = mesh.tria3["IDtag"] triaD = np.empty((mesh.tria3.shape[0]), dtype=jigsaw_msh_t.TRIA3_t) triaD["index"][:, 0] = node4 triaD["index"][:, 1] = node5 triaD["index"][:, 2] = node6 triaD["IDtag"] = mesh.tria3["IDtag"] mesh.tria3 = np.concatenate((triaA, triaB, triaC, triaD), axis=+0) if (mesh.quad4 is not None and mesh.quad4.size != +0): #------------------------------ create new indexes for QUAD4 node1 = mesh.quad4["index"][:, 0] node2 = mesh.quad4["index"][:, 1] node3 = mesh.quad4["index"][:, 2] node4 = mesh.quad4["index"][:, 3] node5 = \ enew[emap.quad4.index[:, 0]] node6 = \ enew[emap.quad4.index[:, 1]] node7 = \ enew[emap.quad4.index[:, 2]] node8 = \ enew[emap.quad4.index[:, 3]] node9 = \ qnew[qmap.quad4.index[:, 0]] quadA = np.empty((mesh.quad4.shape[0]), dtype=jigsaw_msh_t.QUAD4_t) quadA["index"][:, 0] = node1 quadA["index"][:, 1] = node5 quadA["index"][:, 2] = node9 quadA["index"][:, 3] = node8 quadA["IDtag"] = mesh.quad4["IDtag"] quadB = np.empty((mesh.quad4.shape[0]), dtype=jigsaw_msh_t.QUAD4_t) quadB["index"][:, 0] = node2 quadB["index"][:, 1] = node6 quadB["index"][:, 2] = node9 quadB["index"][:, 3] = node5 quadB["IDtag"] = mesh.quad4["IDtag"] quadC = np.empty((mesh.quad4.shape[0]), dtype=jigsaw_msh_t.QUAD4_t) quadC["index"][:, 0] = node3 quadC["index"][:, 1] = node7 quadC["index"][:, 2] = node9 quadC["index"][:, 3] = node6 quadC["IDtag"] = mesh.quad4["IDtag"] quadD = np.empty((mesh.quad4.shape[0]), dtype=jigsaw_msh_t.QUAD4_t) quadD["index"][:, 0] = node4 quadD["index"][:, 1] = node8 quadD["index"][:, 2] = node9 quadD["index"][:, 3] = node7 quadD["IDtag"] = mesh.quad4["IDtag"] mesh.quad4 = np.concatenate((quadA, quadB, quadC, quadD), axis=+0) if (mesh.tria4 is not None and mesh.tria4.size != +0): #------------------------------ create new indexes for TRIA4 node1 = mesh.tria4["index"][:, 0] node2 = mesh.tria4["index"][:, 1] node3 = mesh.tria4["index"][:, 2] node4 = mesh.tria4["index"][:, 3] nodeA = \ enew[emap.tria4.index[:, 0]] nodeB = \ enew[emap.tria4.index[:, 1]] nodeC = \ enew[emap.tria4.index[:, 2]] nodeD = \ enew[emap.tria4.index[:, 3]] nodeE = \ enew[emap.tria4.index[:, 4]] nodeF = \ enew[emap.tria4.index[:, 5]] verts = mesh.point # 1st subdiv. of octahedron triaA = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaA["index"][:, 0] = nodeC triaA["index"][:, 1] = nodeE triaA["index"][:, 2] = nodeA triaA["index"][:, 3] = nodeB triaA["IDtag"] = mesh.tria4["IDtag"] triaB = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaB["index"][:, 0] = nodeC triaB["index"][:, 1] = nodeE triaB["index"][:, 2] = nodeB triaB["index"][:, 3] = nodeF triaB["IDtag"] = mesh.tria4["IDtag"] triaC = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaC["index"][:, 0] = nodeC triaC["index"][:, 1] = nodeE triaC["index"][:, 2] = nodeF triaC["index"][:, 3] = nodeD triaC["IDtag"] = mesh.tria4["IDtag"] triaD = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaD["index"][:, 0] = nodeC triaD["index"][:, 1] = nodeE triaD["index"][:, 2] = nodeD triaD["index"][:, 3] = nodeA triaD["IDtag"] = mesh.tria4["IDtag"] costA = triscr3(verts["coord"], triaA["index"]) costB = triscr3(verts["coord"], triaB["index"]) costC = triscr3(verts["coord"], triaC["index"]) costD = triscr3(verts["coord"], triaD["index"]) cost1 = np.minimum(costA, costB) cost1 = np.minimum(cost1, costC) cost1 = np.minimum(cost1, costD) # 2nd subdiv. of octahedron triaE = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaE["index"][:, 0] = nodeA triaE["index"][:, 1] = nodeF triaE["index"][:, 2] = nodeE triaE["index"][:, 3] = nodeB triaE["IDtag"] = mesh.tria4["IDtag"] triaF = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaF["index"][:, 0] = nodeA triaF["index"][:, 1] = nodeF triaF["index"][:, 2] = nodeB triaF["index"][:, 3] = nodeC triaF["IDtag"] = mesh.tria4["IDtag"] triaG = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaG["index"][:, 0] = nodeA triaG["index"][:, 1] = nodeF triaG["index"][:, 2] = nodeC triaG["index"][:, 3] = nodeD triaG["IDtag"] = mesh.tria4["IDtag"] triaH = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaH["index"][:, 0] = nodeA triaH["index"][:, 1] = nodeF triaH["index"][:, 2] = nodeD triaH["index"][:, 3] = nodeE triaH["IDtag"] = mesh.tria4["IDtag"] costE = triscr3(verts["coord"], triaE["index"]) costF = triscr3(verts["coord"], triaF["index"]) costG = triscr3(verts["coord"], triaG["index"]) costH = triscr3(verts["coord"], triaH["index"]) cost2 = np.minimum(costE, costF) cost2 = np.minimum(cost2, costG) cost2 = np.minimum(cost2, costH) # 3rd subdiv. of octahedron triaI = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaI["index"][:, 0] = nodeB triaI["index"][:, 1] = nodeD triaI["index"][:, 2] = nodeA triaI["index"][:, 3] = nodeE triaI["IDtag"] = mesh.tria4["IDtag"] triaJ = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaJ["index"][:, 0] = nodeB triaJ["index"][:, 1] = nodeD triaJ["index"][:, 2] = nodeE triaJ["index"][:, 3] = nodeF triaJ["IDtag"] = mesh.tria4["IDtag"] triaK = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaK["index"][:, 0] = nodeB triaK["index"][:, 1] = nodeD triaK["index"][:, 2] = nodeF triaK["index"][:, 3] = nodeC triaK["IDtag"] = mesh.tria4["IDtag"] triaL = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) triaL["index"][:, 0] = nodeB triaL["index"][:, 1] = nodeD triaL["index"][:, 2] = nodeC triaL["index"][:, 3] = nodeA triaL["IDtag"] = mesh.tria4["IDtag"] costI = triscr3(verts["coord"], triaI["index"]) costJ = triscr3(verts["coord"], triaJ["index"]) costK = triscr3(verts["coord"], triaK["index"]) costL = triscr3(verts["coord"], triaL["index"]) cost3 = np.minimum(costI, costJ) cost3 = np.minimum(cost3, costK) cost3 = np.minimum(cost3, costL) # 4 cells in tetra. corners tria1 = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) tria1["index"][:, 0] = node1 tria1["index"][:, 1] = nodeA tria1["index"][:, 2] = nodeC tria1["index"][:, 3] = nodeD tria1["IDtag"] = mesh.tria4["IDtag"] tria2 = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) tria2["index"][:, 0] = node2 tria2["index"][:, 1] = nodeB tria2["index"][:, 2] = nodeA tria2["index"][:, 3] = nodeE tria2["IDtag"] = mesh.tria4["IDtag"] tria3 = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) tria3["index"][:, 0] = node3 tria3["index"][:, 1] = nodeC tria3["index"][:, 2] = nodeB tria3["index"][:, 3] = nodeF tria3["IDtag"] = mesh.tria4["IDtag"] tria4 = np.empty((mesh.tria4.shape[0]), dtype=jigsaw_msh_t.TRIA4_t) tria4["index"][:, 0] = nodeD tria4["index"][:, 1] = nodeE tria4["index"][:, 2] = nodeF tria4["index"][:, 3] = node4 tria4["IDtag"] = mesh.tria4["IDtag"] # subdiv. with max(min(scr)) index = np.argsort(np.stack((cost1, cost2, cost3), axis=1), axis=1) mesh.tria4 = np.concatenate( ( tria1, tria2, tria3, tria4, triaA[index[:, 2] == 0], # subdiv. 1 triaB[index[:, 2] == 0], triaC[index[:, 2] == 0], triaD[index[:, 2] == 0], triaE[index[:, 2] == 1], # subdiv. 2 triaF[index[:, 2] == 1], triaG[index[:, 2] == 1], triaH[index[:, 2] == 1], triaI[index[:, 2] == 2], # subdiv. 3 triaJ[index[:, 2] == 2], triaK[index[:, 2] == 2], triaL[index[:, 2] == 2]), axis=0) return
def savemsh(name, mesh, tags=None): """ SAVEMSH: save a JIGSAW MSH object to file. SAVEMSH(NAME, MESH) MESH is JIGSAW's primary mesh/grid/geom class. See MSH_t for details. Data in MESH is written as-needed -- any objects defined will be saved to file. """ if (not isinstance(name, str)): raise Exception("Incorrect type: NAME.") if (not isinstance(mesh, jigsaw_msh_t)): raise Exception("Incorrect type: MESH.") certify(mesh) class stub(object): pass args = stub() ## savmsh params args.kind = "ascii" args.nver = +3 args.prec = +17 args.real = "f64" args.ints = "i32" fext = Path(name).suffix if (fext.strip() != ".msh"): name += ".msh" kind = mesh.mshID.lower() if (tags is not None): #----------------------------------- parse savmsh params stag = tags.lower().split(";") for this in stag: if "precision" in this: args.prec = this.split("=")[1] args.prec = int(args.prec) if "real:type" in this: args.real = this.split("=")[1] if "ints:type" in this: args.ints = this.split("=")[1] if "binary" in this: args.kind = "binary" with Path(name).open("w") as fptr: #----------------------------------- write JIGSAW object fptr.write("# " + Path(name).name + "; created by JIGSAW's PYTHON interface \n") if (kind == "euclidean-mesh"): save_mesh_file(mesh, fptr, args, "euclidean-mesh") if (kind == "euclidean-grid"): save_grid_file(mesh, fptr, args, "euclidean-grid") if (kind == "ellipsoid-mesh"): save_mesh_file(mesh, fptr, args, "ellipsoid-mesh") if (kind == "ellipsoid-grid"): save_grid_file(mesh, fptr, args, "ellipsoid-grid") return
def project(mesh, proj, sign): """ PROJECT cartographic projections for JIGSAW MSH objects. PROJECT(MESH,PROJ,SIGN) returns the projected mesh object MESH resulting from application of the projection operator PROJ to the input object MESH. SIGN is a string defining the "sense" of the projection, either SIGN="FWD" for forward projections or SIGN="INV" for the inverse operation. The following projection operators are supported: PROJ.PRJID = "stereographic" PROJ.RADII = # sphere radii. PROJ.XBASE = # central XLON. PROJ.YBASE = # central YLAT. """ if (not isinstance(mesh, jigsaw_msh_t)): raise Exception("Incorrect type: MESH.") if (not isinstance(proj, jigsaw_prj_t)): raise Exception("Incorrect type: PROJ.") if (not isinstance(sign, str)): raise Exception("Incorrect type: SIGN.") certify(mesh) kind = mesh.mshID.lower() if (kind == "euclidean-mesh" or kind == "ellipsoid-mesh"): #------------------------------- proj. from MESH to MESH if (mesh.vert2 is not None and mesh.vert2.size != +0): XPOS = mesh.point["coord"][:, 0] YPOS = mesh.point["coord"][:, 1] #----------------------------------- proj. geometry parts if (proj.prjID.lower() == "stereographic"): XNEW, YNEW, SCAL = stereo3( proj.radii, XPOS, YPOS, proj.xbase, proj.ybase, sign) """ elif (proj.prjID.lower() == "hammer-aitoff"): XNEW, YNEW, SCAL = hammer3( proj.radii, XPOS, YPOS, proj.xbase, proj.ybase, sign) """ else: raise Exception( "Projection operator not suppoted.") #----------------------------------- setup proj.'d object if (sign.lower() == "fwd"): mesh.mshID = "euclidean-mesh" if (mesh.radii is not None): mesh.radii = None elif (sign.lower() == "inv"): mesh.mshID = "ellipsoid-mesh" mesh.radii = np.full( +3, proj.radii, dtype=jigsaw_msh_t.REALS_t) else: raise Exception( "Incorrect projection PRJID flags.") mesh.point["coord"][:, 0] = XNEW mesh.point["coord"][:, 1] = YNEW #----------------------------------- setup proj.'d extras if (mesh.value is not None and mesh.value.size != +0): mesh.value = mesh.value * SCAL if (mesh.power is not None and mesh.power.size != +0): SPOW = np.sqrt(SCAL) mesh.power = mesh.power * SPOW elif (kind == "euclidean-grid" or kind == "ellipsoid-grid"): #------------------------------- proj. from GRID to MESH if (mesh.xgrid is not None and mesh.xgrid.size != +0 and mesh.ygrid is not None and mesh.ygrid.size != +0): XPOS, YPOS = \ np.meshgrid(mesh.xgrid, mesh.ygrid) XPOS = np.reshape(XPOS, (XPOS.size)) YPOS = np.reshape(YPOS, (YPOS.size)) #----------------------------------- proj. geometry parts if (proj.prjID.lower() == "stereographic"): XNEW, YNEW, SCAL = stereo3( proj.radii, XPOS, YPOS, proj.xbase, proj.ybase, sign) """ elif (proj.prjID.lower() == "hammer-aitoff"): XNEW, YNEW, SCAL = hammer3( proj.radii, XPOS, YPOS, proj.xbase, proj.ybase, sign) """ else: raise Exception( "Projection operator not suppoted.") #----------------------------------- setup proj.'d object mesh.point = np.empty( XNEW.size, dtype=jigsaw_msh_t.VERT2_t) if (sign.lower() == "fwd"): mesh.mshID = "euclidean-mesh" if (mesh.radii is not None): mesh.radii = None elif (sign.lower() == "inv"): mesh.mshID = "ellipsoid-mesh" mesh.radii = np.full( +3, proj.radii, dtype=jigsaw_msh_t.REALS_t) else: raise Exception( "Incorrect projection PRJID flags.") mesh.point["IDtag"] = +0 mesh.point["coord"][:, 0] = XNEW mesh.point["coord"][:, 1] = YNEW #----------------------------------- setup proj.'d topol. mesh.tria3 = np.empty( +0, dtype=jigsaw_msh_t.TRIA3_t) dim1 = mesh.xgrid.size mesh.xgrid = None dim2 = mesh.ygrid.size mesh.ygrid = None tset = [] for jpos in range(dim2 - 1): #----------------------------------- 1st tria. per column triaA = np.empty( dim1 - 1, dtype=mesh.TRIA3_t) triaA["IDtag"] = 0 index = triaA["index"] index[:, 0] = range(0, dim1 - 1) index[:, 0] += (jpos + 0) * dim1 index[:, 1] = range(1, dim1 - 0) index[:, 1] += (jpos + 0) * dim1 index[:, 2] = range(1, dim1 - 0) index[:, 2] += (jpos + 1) * dim1 tset.append(triaA) #----------------------------------- 2nd tria. per column triaB = np.empty( dim1 - 1, dtype=mesh.TRIA3_t) triaB["IDtag"] = 0 index = triaB["index"] index[:, 0] = range(0, dim1 - 1) index[:, 0] += (jpos + 0) * dim1 index[:, 1] = range(1, dim1 - 0) index[:, 1] += (jpos + 1) * dim1 index[:, 2] = range(0, dim1 - 1) index[:, 2] += (jpos + 1) * dim1 tset.append(triaB) mesh.tria3 = \ np.concatenate(tset, axis=0) #----------------------------------- setup proj.'d extras if (mesh.slope is not None and mesh.slope.size != +0): mesh.slope = np.reshape( mesh.slope, mesh.slope.size) if (mesh.value is not None and mesh.value.size != +0): mesh.value = np.reshape( mesh.value, mesh.value.size) mesh.value = mesh.value * SCAL if (mesh.power is not None and mesh.power.size != +0): mesh.power = np.reshape( mesh.power, mesh.power.size) SPOW = np.sqrt(SCAL) mesh.power = mesh.power * SPOW return