def WriteGid(mesh, filename): """ Write a GiD file with the given filename """ debug.dprint("Writing GiD mesh with filename " + filename) fileHandle = open(filename, "w") # Write the header fileHandle.write(utils.FormLine(["MESH", "dimension", mesh.GetDim(), "ElemType", "Unknown", "Nnode", mesh.VolumeElementFixedNodeCount()])) # Write the nodes fileHandle.write("Coordinates\n") for i, nodeCoord in enumerate(mesh.GetNodeCoords()): fileHandle.write(" " + utils.FormLine([i + 1, nodeCoord])) fileHandle.write("end coordinates\n") # Write the volume elements fileHandle.write("Elements\n") for i, element in enumerate(mesh.GetVolumeElements()): # Note: GiD file indexes nodes from 1, Mesh s index nodes from 0 fileHandle.write(" " + utils.FormLine([i + 1, ToGidNodeOrder(utils.OffsetList(element.GetNodes(), 1), elements.ElementType(dim = mesh.GetDim(), nodeCount = element.NodeCount()))])) fileHandle.write("end elements\n") fileHandle.close() debug.dprint("Finished writing GiD mesh") return mesh
def SItem(s, key, delimiter): if key in s: return s[key] else: keySplit = key.split(delimiter) for i in range(len(keySplit)): key = utils.FormLine(keySplit[:i], delimiter=delimiter, newline=False) if key in s: if isinstance(s[key], dict): try: # Tolerate a failure when recursing, as the key may have been # eroneously split return SItem( s[key], utils.FormLine(keySplit[i:], delimiter=delimiter, newline=False), delimiter) except Exception: pass else: return s[key] raise Exception("Key not found")
def WriteHalos(halos, filename): """ Write a Fluidity .halo file """ xmlfile = xml.dom.minidom.Document() halosRootEle = xmlfile.createElement("halos") halosRootEle.setAttribute("process", str(halos.GetProcess())) halosRootEle.setAttribute("nprocs", str(halos.GetNProcesses())) xmlfile.appendChild(halosRootEle) halos = halos.LevelHaloDict() for level in halos.keys(): halo = halos[level] haloEle = xmlfile.createElement("halo") haloEle.setAttribute("level", str(level)) haloEle.setAttribute("n_private_nodes", str(halo.GetNOwnedNodes())) halosRootEle.appendChild(haloEle) for i, process in enumerate(range(halo.GetNProcesses())): haloDataEle = xmlfile.createElement("halo_data") haloDataEle.setAttribute("process", str(i)) haloEle.appendChild(haloDataEle) sendEle = xmlfile.createElement("send") haloDataEle.appendChild(sendEle) if level > 0: sendText = xmlfile.createTextNode(utils.FormLine(utils.OffsetList(utils.ExpandList(halo.GetSends(process = i)), 1), delimiter = " ", newline = False)) else: sendText = xmlfile.createTextNode(utils.FormLine(utils.ExpandList(halo.GetSends(process = i)), delimiter = " ", newline = False)) sendEle.appendChild(sendText) receiveEle = xmlfile.createElement("receive") haloDataEle.appendChild(receiveEle) if level > 0: receiveText = xmlfile.createTextNode(utils.FormLine(utils.OffsetList(utils.ExpandList(halo.GetReceives(process = i)), 1), delimiter = " ", newline = False)) else: receiveText = xmlfile.createTextNode(utils.FormLine(utils.ExpandList(halo.GetReceives(process = i)), delimiter = " ", newline = False)) receiveEle.appendChild(receiveText) handle = open(filename, "w") if XmlExtSupport(): xml.dom.ext.PrettyPrint(xmlfile, handle) else: xmlfile.writexml(handle) handle.flush() handle.close() return
def TetrahedralizePoly(polyFilename, commandLineSwitches=[]): """ Tetrahedralise the given poly using TetGen """ assert (filehandling.FileExtension(polyFilename) == ".poly") tempDir = tempfile.mkdtemp() tempFile = os.path.join(tempDir, os.path.basename(polyFilename)) filehandling.Cp(polyFilename, tempFile) command = ["tetgen", "-p"] if debug.GetDebugLevel() > 1: command.append("-V") stdout = None stderr = None else: stdout = subprocess.PIPE stderr = subprocess.PIPE command += commandLineSwitches command.append(tempFile) debug.dprint("Tetrahedralization command: " + utils.FormLine(command, delimiter=" ", newline=False)) proc = subprocess.Popen(command, stdout=stdout, stderr=stderr) proc.wait() assert (proc.returncode == 0) mesh = triangletools.ReadTriangle(tempFile[:-5] + ".1") filehandling.Rmdir(tempDir, force=True) return mesh
def StripFileExtension(filename): """ Strip the file extension from the supplied filename """ split = os.path.basename(filename).split(".") if len(split) == 1: return filename else: return os.path.join(os.path.dirname(filename), utils.FormLine(split[:-1], delimiter = ".", newline = False))
def SplitVtuFilename(filename): """ Split the supplied vtu filename into project, ID and file extension """ first = filehandling.StripFileExtension(filename) ext = filehandling.FileExtension(filename) split = first.split("_") + [ext] idIndex = None for i, val in enumerate(split[1:]): if utils.IsIntString(val): idIndex = i + 1 break assert (not idIndex is None) project = utils.FormLine(split[:idIndex], delimiter="_", newline=False) id = int(split[idIndex]) ext = utils.FormLine([""] + split[idIndex + 1:len(split) - 1], delimiter="_", newline=False) + split[-1] return project, id, ext
def WriteTriangle(mesh, baseName): """ Write triangle files with the given base name """ def FileFooter(): return "# Created by triangletools.WriteTriangle\n" + \ "# Command: " + " ".join(sys.argv) + "\n" + \ "# " + str(time.ctime()) + "\n" debug.dprint("Writing triangle mesh with base name " + baseName) # Write the .node file debug.dprint("Writing .node file") nodeHandle = open(baseName + ".node", "w") # Write the meta data nodeHandle.write(utils.FormLine([mesh.NodeCount(), mesh.GetDim(), 0, 0])) # Write the nodes for i in range(mesh.NodeCount()): nodeHandle.write(utils.FormLine([i + 1, mesh.GetNodeCoord(i)])) nodeHandle.write(FileFooter()) nodeHandle.close() if mesh.GetDim() == 1: # Write the .bound file debug.dprint("Writing .bound file") boundHandle = open(baseName + ".bound", "w") # Write the meta data nBoundIds = 0 for i in range(mesh.SurfaceElementCount()): if i == 0: nBoundIds = len(mesh.GetSurfaceElement(i).GetIds()) else: assert(nBoundIds == len(mesh.GetSurfaceElement(i).GetIds())) boundHandle.write(utils.FormLine([mesh.SurfaceElementCount(), nBoundIds])) # Write the bounds for i in range(mesh.SurfaceElementCount()): boundHandle.write(utils.FormLine([i + 1, utils.OffsetList(mesh.GetSurfaceElement(i).GetNodes(), 1), mesh.GetSurfaceElement(i).GetIds()])) boundHandle.write(FileFooter()) boundHandle.close() elif mesh.GetDim() == 2: # Write the .edge file debug.dprint("Writing .edge file") edgeHandle = open(baseName + ".edge", "w") # Write the meta data nEdgeIds = 0 for i in range(mesh.SurfaceElementCount()): if i == 0: nEdgeIds = len(mesh.GetSurfaceElement(i).GetIds()) else: assert(nEdgeIds == len(mesh.GetSurfaceElement(i).GetIds())) edgeHandle.write(utils.FormLine([mesh.SurfaceElementCount(), nEdgeIds])) # Write the edges for i in range(mesh.SurfaceElementCount()): edgeHandle.write(utils.FormLine([i + 1, utils.OffsetList(mesh.GetSurfaceElement(i).GetNodes(), 1), mesh.GetSurfaceElement(i).GetIds()])) edgeHandle.write(FileFooter()) edgeHandle.close() elif mesh.GetDim() == 3: # Write the .face file debug.dprint("Writing .face file") faceHandle = open(baseName + ".face", "w") # Write the meta data nFaceIds = 0 for i in range(mesh.SurfaceElementCount()): if i == 0: nFaceIds = len(mesh.GetSurfaceElement(i).GetIds()) else: assert(nFaceIds == len(mesh.GetSurfaceElement(i).GetIds())) faceHandle.write(utils.FormLine([mesh.SurfaceElementCount(), nFaceIds])) # Write the faces for i in range(mesh.SurfaceElementCount()): faceHandle.write(utils.FormLine([i + 1, utils.OffsetList(mesh.GetSurfaceElement(i).GetNodes(), 1), mesh.GetSurfaceElement(i).GetIds()])) faceHandle.write(FileFooter()) faceHandle.close() # Write the .ele file debug.dprint("Writing .ele file") eleHandle = open(baseName + ".ele", "w") # Write the meta data nNodesPerEle = 0 nEleIds = 0 for i in range(mesh.VolumeElementCount()): if i == 0: nEleIds = len(mesh.GetVolumeElement(i).GetIds()) nNodesPerEle = mesh.GetVolumeElement(i).GetLoc() else: assert(nEleIds == len(mesh.GetVolumeElement(i).GetIds())) assert(nNodesPerEle == mesh.GetVolumeElement(i).GetLoc()) eleHandle.write(utils.FormLine([mesh.VolumeElementCount(), nNodesPerEle, nEleIds])) # Write the eles for i in range(mesh.VolumeElementCount()): # Note: Triangle mesh indexes nodes from 1, Mesh s index nodes from 0 eleHandle.write(utils.FormLine([i + 1, utils.OffsetList(mesh.GetVolumeElement(i).GetNodes(), 1), mesh.GetVolumeElement(i).GetIds()])) eleHandle.write(FileFooter()) eleHandle.close() halos = mesh.GetHalos() if halos.HaloCount() > 0: # Write the .halo file debug.dprint("Writing .halo file") if mesh_halos.HaloIOSupport(): mesh_halos.WriteHalos(halos, baseName + ".halo") else: debug.deprint("Warning: No .halo I/O support") debug.dprint("Finished writing triangle file") return
def WritePoly(mesh, filename, holeMesh=None): """ Write a .poly file with the given base name """ def FileFooter(): return "# Created by WritePoly\n" + \ "# Command: " + " ".join(sys.argv) + "\n" + \ "# " + str(time.ctime()) + "\n" polyHandle = open(filename, "w") # Write the node meta data polyHandle.write("# Nodes\n") polyHandle.write(utils.FormLine([mesh.NodeCount(), mesh.GetDim(), 0, 0])) # Write the nodes for i in range(mesh.NodeCount()): polyHandle.write(utils.FormLine([i + 1, mesh.GetNodeCoord(i)])) # Write the facets meta data polyHandle.write("# Facets\n") nFacetIds = 0 for i in range(mesh.SurfaceElementCount()): if i == 0: nFacetIds = len(mesh.GetSurfaceElement(i).GetIds()) else: assert (nFacetIds == len(mesh.GetSurfaceElement(i).GetIds())) polyHandle.write(utils.FormLine([mesh.SurfaceElementCount(), nFacetIds])) # Write the facets if mesh.GetDim() == 2: # This is the facet specification as in the Triangle documentation # http://www.cs.cmu.edu/~quake/triangle.poly.html for i in range(mesh.SurfaceElementCount()): # Note: .poly indexes nodes from 1, Mesh s index nodes from 0 polyHandle.write( utils.FormLine([ i + 1, utils.OffsetList(mesh.GetSurfaceElement(i).GetNodes(), 1), mesh.GetSurfaceElement(i).GetIds() ])) else: # This is the facet specification as in the Tetgen documentation # http://tetgen.berlios.de/fformats.poly.html for i in range(mesh.SurfaceElementCount()): polyHandle.write( utils.FormLine([1, 0, mesh.GetSurfaceElement(i).GetIds()])) # Note: .poly indexes nodes from 1, Mesh s index nodes from 0 polyHandle.write( utils.FormLine([ mesh.GetSurfaceElement(i).NodeCount(), utils.OffsetList(mesh.GetSurfaceElement(i).GetNodes(), 1) ])) # Write the hole list meta data polyHandle.write("# Holes\n") if holeMesh is None: polyHandle.write(utils.FormLine([0])) else: polyHandle.write(utils.FormLine([holeMesh.NodeCount()])) # Write the holes for i in range(holeMesh.NodeCount()): polyHandle.write(utils.FormLine([i + 1, holeMesh.GetNodeCoord(i)])) polyHandle.write(FileFooter()) polyHandle.close() return
def WriteMsh(mesh, filename, binary = True): """ Write a Gmsh msh file """ if binary: # Binary format fileHandle = open(filename, "wb") # Write the MeshFormat section fileHandle.write("$MeshFormat\n") version = 2.1 fileType = 1 dataSize = ctypes.sizeof(ctypes.c_double) fileHandle.write(utils.FormLine([version, fileType, dataSize])) iArr = array.array("i", [1]) iArr.tofile(fileHandle) fileHandle.write("\n") fileHandle.write("$EndMeshFormat\n") # Write the Nodes section fileHandle.write("$Nodes\n") fileHandle.write(utils.FormLine([mesh.NodeCoordsCount()])) for i, nodeCoord in enumerate(mesh.GetNodeCoords()): nodeCoord = list(nodeCoord) while len(nodeCoord) < 3: nodeCoord.append(0.0) assert(len(nodeCoord) == 3) iArr = array.array("i", [i + 1]) rArr = array.array("d", nodeCoord) iArr.tofile(fileHandle) rArr.tofile(fileHandle) fileHandle.write("\n") fileHandle.write("$EndNodes\n") # Write the Elements section fileHandle.write("$Elements\n") fileHandle.write(utils.FormLine([mesh.SurfaceElementCount() + mesh.VolumeElementCount()])) eleSort = {} for ele in mesh.GetSurfaceElements() + mesh.GetVolumeElements(): eleType = ele.GetType() gmshType = GmshElementType(dim = eleType.GetDim(), nodeCount = eleType.GetNodeCount()) key = (gmshType.GetGmshElementTypeId(), len(ele.GetIds())) if key in eleSort: eleSort[key].append(ele) else: eleSort[key] = [ele] index = 1 for gmshEleId, nIds in eleSort: eles = eleSort[(gmshEleId, nIds)] iArr = array.array("i", [gmshEleId, len(eles), nIds]) iArr.tofile(fileHandle) for ele in eles: iArr = array.array("i", [index] + list(ele.GetIds()) + utils.OffsetList(ToGmshNodeOrder(ele.GetNodes(), ele.GetType()), 1)) iArr.tofile(fileHandle) index += 1 assert(index == mesh.SurfaceElementCount() + mesh.VolumeElementCount() + 1) fileHandle.write("\n") fileHandle.write("$EndElements\n") else: # ASCII format fileHandle = open(filename, "w") # Write the MeshFormat section fileHandle.write("$MeshFormat\n") version = 2.1 fileType = 0 dataSize = ctypes.sizeof(ctypes.c_double) fileHandle.write(utils.FormLine([version, fileType, dataSize])) fileHandle.write("$EndMeshFormat\n") # Write the Nodes section fileHandle.write("$Nodes\n") fileHandle.write(utils.FormLine([mesh.NodeCoordsCount()])) for i, nodeCoord in enumerate(mesh.GetNodeCoords()): nodeCoord = list(nodeCoord) while len(nodeCoord) < 3: nodeCoord.append(0.0) assert(len(nodeCoord) == 3) fileHandle.write(utils.FormLine([i + 1, nodeCoord])) fileHandle.write("$EndNodes\n") # Write the Elements section fileHandle.write("$Elements\n") fileHandle.write(utils.FormLine([mesh.SurfaceElementCount() + mesh.VolumeElementCount()])) for i, ele in enumerate(mesh.GetSurfaceElements() + mesh.GetVolumeElements()): eleType = ele.GetType() gmshType = GmshElementType(dim = eleType.GetDim(), nodeCount = eleType.GetNodeCount()) ids = ele.GetIds() fileHandle.write(utils.FormLine([i + 1, gmshType.GetGmshElementTypeId(), len(ids), ids, utils.OffsetList(ToGmshNodeOrder(ele.GetNodes(), eleType), 1)])) fileHandle.write("$EndElements\n") return
def DetectorArrays(stat): """ Return a dictionary of detector array lists contained in the supplied stat """ # Detector array data is divided in the stat into one path per array entry. We # want to collapse this into a dictionary of one path per array. This involves # lots of horrible parsing of stat paths. # Find all detector array names and the paths for each entry in the array arrays = {} # The arrays notArrayNames = [] # List of candidate array names that are, in fact, not # detector array names for path in stat.PathLists(): if isinstance(stat[stat.FormPathFromList(path)], Stat): # This isn't a leaf node continue # Look for an array marker in the path. This appears as: # [path]%arrayname_index[%component] # and for coordinates as: # arrayname_index[%component] if len(path) >= 2 and path[1] == "position": # This might be a coordinate entry firstKey = path[0] keySplit = firstKey.split("_") # We have an entry in an array if: # 1. We have more than one entry in the split # 2. The final entry in the split contains one of zero (for scalars) or # two (for vector and tensors) array path delimiters # 3. The first stat path split of the final entry is an integer (the # index) if len(keySplit) <= 1 \ or not len(stat.SplitPath(keySplit[-1])) in [1, 2] \ or not utils.IsIntString(stat.SplitPath(keySplit[-1])[0]): # This definitely can't be an entry in a detector array continue # OK, we have something that looks a bit like an entry for a detector # array # Find the array name and the index for this entry arrayName = utils.FormLine( [utils.FormLine(keySplit[:-1], delimiter="_", newline=False)] + path[1:], delimiter=stat.GetDelimiter(), newline=False) index = int(keySplit[-1]) else: # This might be a field entry finalKey = path[-1] keySplit = finalKey.split("_") # We have an entry in an array if: # 1. We have more than one entry in the split # 2. The final entry in the split contains one of zero or one (for field # components) array path delimiters # 3. The first stat path split of the final entry is an integer (the # index) if len(keySplit) <= 1 \ or not len(stat.SplitPath(keySplit[-1])) in [1, 2] \ or not utils.IsIntString(stat.SplitPath(keySplit[-1])[0]): # This definitely can't be an entry in a detector array continue # OK, we have something that looks a bit like an entry for a detector # array # Find the array name and the index for this entry arrayName = utils.FormLine( path[:-1] + [utils.FormLine(keySplit[:-1], delimiter="_", newline=False)], delimiter=stat.GetDelimiter(), newline=False) if len(stat.SplitPath(keySplit[-1])) > 1: # This array name references a field component # We need to append the component to the array name. This needs to be # added to the last but one part of the stat path (the final entry is the # name of this detector array as configured in Fluidity). splitName = stat.SplitPath(arrayName) splitName[-2] = stat.FormPath(splitName[-2], stat.SplitPath(keySplit[-1])[1]) arrayName = stat.FormPathFromList(splitName) index = int(stat.SplitPath(keySplit[-1])[0]) else: # This array name references a field index = int(keySplit[-1]) if arrayName in notArrayNames: # We've already discovered that this candidate array name isn't in fact a # detector array continue if index <= 0: # This isn't a valid index # This candidate array name isn't in fact a detector array notArrayNames.append(arrayName) if arrayName in arrays: arrays.remove(arrayName) continue if arrayName in arrays and index in arrays[arrayName]: # We've seen this index more than once for this array name # This candidate apparent array name isn't in fact a detector array notArrayNames.append(arrayName) arrays.remove(arrayName) continue if arrayName in arrays: arrays[arrayName][index] = stat[stat.FormPathFromList(path)] else: # This is a new array name arrays[arrayName] = {} arrays[arrayName][index] = stat[stat.FormPathFromList(path)] # Convert the dictionaries of data to lists, and check for consecutive # indices for name in arrays: array = arrays[name] indices = array.keys() data = [array[index] for index in indices] indices, data = utils.KeyedSort(indices, data, returnSortedKeys=True) arrays[name] = numpy.array(data) for i, index in enumerate(indices): if not i + 1 == index: # The indices are not consecutive from one. After all the hard work # above, we still have an array name that isn't in fact a detector # array. arrays.remove(name) break # Fantastic! We have our detectors dictionary! debug.dprint("Detector keys:") debug.dprint(arrays.keys()) return arrays