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 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 LinearlyInterpolate(self, x, y): """ Probe the slice data at the supplied coordinate, by linearly interpolating from the surrounding data points. """ assert(self.XCoordsCount() > 0 and self.YCoordsCount() > 0) assert(x >= self.XCoord(0) and x <= self.XCoord(-1)) assert(y >= self.YCoord(0) and y < self.YCoord(-1)) # Peform a binary search for the left index left = calc.IndexBinaryLboundSearch(x, self.XCoords()) # Perform a binary search for the lower index lower = calc.IndexBinaryLboundSearch(y, self.YCoords()) if self.XCoordsCount() > 1: right = left + 1 else: # This is slightly inefficient (could avoid a linear interpolation if we # wanted) right = left if self.YCoordsCount() > 1: upper = lower + 1 else: # This is slightly inefficient (could avoid a linear interpolation if we # wanted) upper = lower debug.dprint("left = " + str(left), 3) debug.dprint("lower = " + str(lower), 3) return calc.BilinearlyInterpolate(self.GetVal(left, upper), self.GetVal(right, upper), self.GetVal(left, lower), self.GetVal(right, lower), \ (x - self.XCoord(left)) / (self.XCoord(right) - self.XCoord(left)), (y - self.YCoord(lower)) / (self.YCoord(upper) - self.YCoord(lower)))
def FluidityBinary( binaries=[ "dfluidity-debug", "dfluidity", "fluidity-debug", "fluidity" ]): """ Return the command used to call Fluidity """ binary = None for possibleBinary in binaries: process = subprocess.Popen(["which", possibleBinary], stdout=subprocess.PIPE, stderr=subprocess.PIPE) process.wait() if process.returncode == 0: binary = possibleBinary debug.dprint("Fluidity binary: " + str(process.stdout.readlines()[0]), newline=False) break if binary is None: raise Exception("Failed to find Fluidity binary") return binary
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 EnableDebugging(): global _debugging _debugging = True debug.dprint("Enabled debugging") return
def DisableDebugging(): global _debugging _debugging = False debug.dprint("Disabled debugging") return
def ReadMsh(filename): """ Read a Gmsh msh file """ fileHandle = open(filename, "rb") basename = filename.split(".")[0] hasHalo = filehandling.FileExists(basename + ".halo") # Read the MeshFormat section line = ReadNonCommentLine(fileHandle) assert (line == "$MeshFormat") line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert (len(lineSplit) == 3) version = lineSplit[0] fileType = int(lineSplit[1]) dataSize = int(lineSplit[2]) if version[0] == "4" and version < "4.1": raise Exception("gmshtools doesn't handle msh4 with minor version 0") if fileType == 1: # Binary format if version[0] == "4": mesh = ReadBinaryMshV4(fileHandle, dataSize) elif version[0] == "2": mesh = ReadBinaryMshV2(fileHandle, dataSize) else: raise Exception("Unknown gmsh major version") elif fileType == 0: # ASCII format if version[0] == "4": mesh = ReadAsciiMshV4(fileHandle) elif version[0] == "2": mesh = ReadAsciiMshV2(fileHandle) else: raise Exception("Unknown gmsh major version") else: raise Exception("File type " + str(fileType) + " not recognised") fileHandle.close() if hasHalo: # Read the .halo file debug.dprint("Reading .halo file") if mesh_halos.HaloIOSupport(): halos = mesh_halos.ReadHalos(basename + ".halo") mesh.SetHalos(halos) else: debug.deprint("Warning: No .halo I/O support") return mesh
def Help(): debug.dprint("Usage: gen_square_meshes [OPTIONS] ... NODES MESHES\n" + \ "\n" + \ "Options:\n" + \ "\n" + \ "-h Display this help\n" + \ "-v Verbose mode", 0) return
def Help(): debug.dprint("Usage: statplot [OPTIONS] FILENAME [FILENAME ...]\n" + \ "\n" + \ "Options:\n" + \ "\n" + \ "-h Display this help\n" + \ "-v Verbose mode", 0) return
def VtuStripFloatingNodes(vtu): """ Strip floating (unconnected) nodes from the supplied vtu """ nodeUsed = numpy.array( [False for i in range(vtu.ugrid.GetNumberOfPoints())]) for i in range(vtu.ugrid.GetNumberOfCells()): cell = vtu.ugrid.GetCell(i) nodeIds = cell.GetPointIds() nodes = [nodeIds.GetId(i) for i in range(nodeIds.GetNumberOfIds())] nodeUsed[nodes] = True nodeMap = [None for i in range(vtu.ugrid.GetNumberOfPoints())] nnodes = 0 for node, used in enumerate(nodeUsed): if used: nodeMap[node] = nnodes nnodes += 1 nFloatingNodes = vtu.ugrid.GetNumberOfPoints() - nnodes debug.dprint("Floating nodes: " + str(nFloatingNodes)) if nFloatingNodes == 0: return coords = vtu.GetLocations() points = vtk.vtkPoints() points.SetDataTypeToDouble() for node, coord in enumerate(coords): if nodeUsed[node]: points.InsertNextPoint(coord[0], coord[1], coord[2]) vtu.ugrid.SetPoints(points) cells = vtk.vtkCellArray() for i in range(vtu.ugrid.GetNumberOfCells()): cell = vtu.ugrid.GetCell(i) nodeIds = cell.GetPointIds() nodes = [nodeIds.GetId(i) for i in range(nodeIds.GetNumberOfIds())] for i, node in enumerate(nodes): assert (not nodeMap[node] is None) nodeIds.SetId(i, nodeMap[node]) cells.InsertNextCell(cell) vtu.ugrid.SetCells(vtu.ugrid.GetCellTypesArray(), vtu.ugrid.GetCellLocationsArray(), cells) for fieldName in vtu.GetFieldNames(): field = vtu.GetField(fieldName) shape = list(field.shape) shape[0] = nnodes nField = numpy.empty(shape) for node, nNode in enumerate(nodeMap): if not nNode is None: nField[nNode] = field[node] vtu.AddField(fieldName, nField) return
def SliceCoordsLinear(minVal, maxVal, minL, divisions, tolerance=calc.Epsilon()): """ Generate one dimension of annulus slice coordinates based upon the supplied geometry information, with linearly stretched node spacing """ assert (minL > 0.0) assert (divisions >= 4) assert (calc.IsEven(divisions)) d = (maxVal - minVal) / 2.0 n = divisions / 2 # Perform a binary search for r - using a numerical solve via # scipy.optimize.fsolve seems to introduce too large an error minR = 1.0 maxR = d / minL r = 0.0 while True: # Calculate a new guess for r oldR = r r = (maxR + minR) / 2.0 if calc.AlmostEquals(r, oldR, tolerance=tolerance): break # Calculate what value of d this implies dGuess = 0.0 for i in range(n): dGuess += minL * (r**i) # Based upon the implied d, choose new bounds for r if calc.AlmostEquals(d, dGuess, tolerance=tolerance): break elif dGuess > d: maxR = r else: minR = r if calc.AlmostEquals(r, 1.0, tolerance=tolerance): raise Exception("No solution for r > 1.0 found") debug.dprint("r = " + str(r), 2) coords = [minVal] for i in range(divisions / 2 - 1): coords.insert(i + 1, coords[i] + (minL * (r**i))) coords.append((maxVal + minVal) / 2.0) coords.append(maxVal) for i in range(divisions / 2 - 1): coords.insert(len(coords) - i - 1, coords[-i - 1] - (minL * (r**i))) return coords
def VtuStripFloatingNodes(vtu): """ Strip floating (unconnected) nodes from the supplied vtu """ nodeUsed = numpy.array([False for i in range(vtu.ugrid.GetNumberOfPoints())]) for i in range(vtu.ugrid.GetNumberOfCells()): cell = vtu.ugrid.GetCell(i) nodeIds = cell.GetPointIds() nodes = [nodeIds.GetId(i) for i in range(nodeIds.GetNumberOfIds())] nodeUsed[nodes] = True nodeMap = [None for i in range(vtu.ugrid.GetNumberOfPoints())] nnodes = 0 for node, used in enumerate(nodeUsed): if used: nodeMap[node] = nnodes nnodes += 1 nFloatingNodes = vtu.ugrid.GetNumberOfPoints() - nnodes debug.dprint("Floating nodes: " + str(nFloatingNodes)) if nFloatingNodes == 0: return coords = vtu.GetLocations() points = vtk.vtkPoints() points.SetDataTypeToDouble() for node, coord in enumerate(coords): if nodeUsed[node]: points.InsertNextPoint(coord[0], coord[1], coord[2]) vtu.ugrid.SetPoints(points) cells = vtk.vtkCellArray() for i in range(vtu.ugrid.GetNumberOfCells()): cell = vtu.ugrid.GetCell(i) nodeIds = cell.GetPointIds() nodes = [nodeIds.GetId(i) for i in range(nodeIds.GetNumberOfIds())] for i, node in enumerate(nodes): assert(not nodeMap[node] is None) nodeIds.SetId(i, nodeMap[node]) cells.InsertNextCell(cell) vtu.ugrid.SetCells(vtu.ugrid.GetCellTypesArray(), vtu.ugrid.GetCellLocationsArray(), cells) for fieldName in vtu.GetFieldNames(): field = vtu.GetField(fieldName) shape = list(field.shape) shape[0] = nnodes nField = numpy.empty(shape) for node, nNode in enumerate(nodeMap): if not nNode is None: nField[nNode] = field[node] vtu.AddField(fieldName, nField) return
def __init__(self, filename, latitudeName = "latitude", longitudeName = "longitude", timeName = "time"): self._file = netcdf.netcdf_file(filename, "r") self._latitudes = self.Values(latitudeName) self._longitudes = self.Values(longitudeName) self._times = self.Values(timeName) # Longitude wrap-around self._longitudes.append(self._longitudes[0] + 360.0) debug.dprint(self) return
def SliceCoordsLinear(minVal, maxVal, minL, divisions, tolerance = calc.Epsilon()): """ Generate one dimension of annulus slice coordinates based upon the supplied geometry information, with linearly stretched node spacing """ assert(minL > 0.0) assert(divisions >= 4) assert(calc.IsEven(divisions)) d = (maxVal - minVal) / 2.0 n = divisions / 2 # Perform a binary search for r - using a numerical solve via # scipy.optimize.fsolve seems to introduce too large an error minR = 1.0 maxR = d / minL r = 0.0 while True: # Calculate a new guess for r oldR = r r = (maxR + minR) / 2.0 if calc.AlmostEquals(r, oldR, tolerance = tolerance): break # Calculate what value of d this implies dGuess = 0.0 for i in range(n): dGuess += minL * (r ** i) # Based upon the implied d, choose new bounds for r if calc.AlmostEquals(d, dGuess, tolerance = tolerance): break elif dGuess > d: maxR = r else: minR = r if calc.AlmostEquals(r, 1.0, tolerance = tolerance): raise Exception("No solution for r > 1.0 found") debug.dprint("r = " + str(r), 2) coords = [minVal] for i in range(divisions / 2 - 1): coords.insert(i + 1, coords[i] + (minL * (r ** i))) coords.append((maxVal + minVal) / 2.0) coords.append(maxVal) for i in range(divisions / 2 - 1): coords.insert(len(coords) - i - 1, coords[-i - 1] - (minL * (r ** i))) return coords
def _initialise_parameters(self): """ Initialise the parameters used in evaluating the Lomb-Scargle periodogram """ self._mean = MeanVal(self._x) self._variance = 0.0 for x in self._x: self._variance += (x - self._mean)**2 self._variance /= float(self.DataPointsCount() - 1) debug.dprint("Mean = " + str(self._mean), 3) debug.dprint("Variance = " + str(self._variance), 3) return
def __init__(self, filename, latitudeName="latitude", longitudeName="longitude", timeName="time"): self._file = netcdf.NetCDFFile(filename, "r") self._latitudes = self.Values(latitudeName) self._longitudes = self.Values(longitudeName) self._times = self.Values(timeName) # Longitude wrap-around self._longitudes.append(self._longitudes[0] + 360.0) debug.dprint(self) return
def _initialise_parameters(self): """ Initialise the parameters used in evaluating the Lomb-Scargle periodogram """ self._mean = MeanVal(self._x) self._variance = 0.0 for x in self._x: self._variance += (x - self._mean) ** 2 self._variance /= float(self.DataPointsCount() - 1) debug.dprint("Mean = " + str(self._mean), 3) debug.dprint("Variance = " + str(self._variance), 3) return
def InterpolatedSSA(v, t, N_T, n, J=1, t0=None, t1=None): """ Perform a singular systems analysis of the supplied non-uniform data using linear interpolation """ if t0 is None: t0 = t[0] if t1 is None: t1 = t[-1] dt = (t1 - t0) / float(N_T) debug.dprint("Interpolation dt: " + str(dt)) lt = [t0 + i * dt for i in range(N_T)] lv = LinearlyInterpolateField(v, t, lt) print(lv, lt) return SSA(lv, n, J=J)
def InterpolatedSSA(v, t, N_T, n, J = 1, t0 = None, t1 = None): """ Perform a singular systems analysis of the supplied non-uniform data using linear interpolation """ if t0 is None: t0 = t[0] if t1 is None: t1 = t[-1] dt = (t1 - t0) / float(N_T) debug.dprint("Interpolation dt: " + str(dt)) lt = [t0 + i * dt for i in range(N_T)] lv = LinearlyInterpolateField(v, t, lt) print(lv, lt) return SSA(lv, n, J = J)
def FluidityBinary(binaries = ["dfluidity-debug", "dfluidity", "fluidity-debug", "fluidity"]): """ Return the command used to call Fluidity """ binary = None for possibleBinary in binaries: process = subprocess.Popen(["which", possibleBinary], stdout = subprocess.PIPE, stderr = subprocess.PIPE) process.wait() if process.returncode == 0: binary = possibleBinary debug.dprint("Fluidity binary: " + str(process.stdout.readlines()[0]), newline = False) break if binary is None: raise Exception("Failed to find Fluidity binary") return binary
def SSA(v, n, J=1): """ Perform a singular systems analysis of the supplied array of data. See: Inertia-Gravity Wave Generation by Baroclinic Instability, Tom Jacoby, First year report, AOPP, September 2007 """ N_T = len(v) N = N_T - (n - 1) * J shape = (n, N) debug.dprint("Assembling matrix for SSA, shape = " + str(shape)) X = numpy.empty(shape) for i in range(N): for j in range(n): X[j, i] = v[i + j * J] theta = numpy.dot(X, X.transpose()) / float(N) del (X) debug.dprint("Performing eigendecomposition") return Eigendecomposition(theta, returnEigenvectors=True)
def SSA(v, n, J = 1): """ Perform a singular systems analysis of the supplied array of data. See: Inertia-Gravity Wave Generation by Baroclinic Instability, Tom Jacoby, First year report, AOPP, September 2007 """ N_T = len(v) N = N_T - (n - 1) * J shape = (n, N) debug.dprint("Assembling matrix for SSA, shape = " + str(shape)) X = numpy.empty(shape) for i in range(N): for j in range(n): X[j, i] = v[i + j * J] theta = numpy.dot(X, X.transpose()) / float(N) del(X) debug.dprint("Performing eigendecomposition") return Eigendecomposition(theta, returnEigenvectors = True)
if len(args) < 2: debug.FatalError("GMSH base name and vtu name required") elif len(args) > 2: debug.FatalError("Unrecognised trailing argument") meshBasename = args[0] vtuFilename = args[1] possibleMeshBasenames = glob.glob(meshBasename + "_?*.msh") meshBasenames = [] meshIds = [] for possibleMeshBasename in possibleMeshBasenames: id = possibleMeshBasename[len(meshBasename) + 1:-4] try: id = int(id) except ValueError: continue meshBasenames.append(possibleMeshBasename[:-4]) meshIds.append(id) vtuBasename = os.path.basename(vtuFilename[:-len(vtuFilename.split(".")[-1]) - 1]) vtuExt = vtuFilename[-len(vtuFilename.split(".")[-1]):] vtu = vtktools.vtu(vtuFilename) for i, meshBasename in enumerate(meshBasenames): debug.dprint("Processing mesh partition " + meshBasename) meshVtu = gmshtools.ReadMsh(meshBasename).ToVtu(includeSurface=False) partition = vtktools.RemappedVtu(vtu, meshVtu) partition.Write(vtuBasename + "_" + str(meshIds[i]) + "." + vtuExt)
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 GenerateAnnulusHorizontalSliceMesh(rCoords, phiCoords, innerWallId = 1, outerWallId = 2, leftWallId = 5, rightWallId = 6, volumeId = 0, connectEnds = True): """ Generate a horizontal annulus slice mesh """ debug.dprint("Generating annulus horizonal slice mesh") if connectEnds: debug.dprint("Annulus is connected") else: debug.dprint("Annulus is blocked") # Copy and sort the input coords lRCoords = copy.deepcopy(rCoords) lPhiCoords = copy.deepcopy(phiCoords) lRCoords.sort() lPhiCoords = [] for phi in phiCoords: while phi < 0.0: phi += 2.0 * math.pi while phi > 2.0 * math.pi: phi -= 2.0 * math.pi lPhiCoords.append(phi) lPhiCoords.sort() phiPoints = len(lPhiCoords) if connectEnds: phiDivisions = phiPoints else: phiDivisions = phiPoints - 1 nRCoords = len(rCoords) # Generate map from r, phi IDs to node IDs rPhiToNode = [] index = 0 for i in range(nRCoords): rPhiToNode.append([]) for j in range(phiPoints): rPhiToNode[i].append(index) index += 1 mesh = meshes.Mesh(2) # Generate node coordinates for r in lRCoords: for phi in lPhiCoords: x = r * math.cos(phi) y = r * math.sin(phi) mesh.AddNodeCoord([x, y]) # Generate volume elements for i in range(nRCoords - 1): debug.dprint("Processing radial element strip " + str(i + 1) + " of " + str(nRCoords - 1), 2) for j in range(phiDivisions): mesh.AddVolumeElement(elements.Element([rPhiToNode[i][j], rPhiToNode[i + 1][j], rPhiToNode[i][(j + 1) % phiPoints]], volumeId)) mesh.AddVolumeElement(elements.Element([rPhiToNode[i + 1][(j + 1) % phiPoints], rPhiToNode[i + 1][j], rPhiToNode[i][(j + 1) % phiPoints]], volumeId)) # Generate surface elements ... # ... for inner wall for i in range(phiDivisions): mesh.AddSurfaceElement(elements.Element([rPhiToNode[0][i], rPhiToNode[0][(i + 1) % phiPoints]], innerWallId)) # ... for outer wall for i in range(phiDivisions): mesh.AddSurfaceElement(elements.Element([rPhiToNode[-1][i], rPhiToNode[-1][(i + 1) % phiPoints]], outerWallId)) if not connectEnds: # ... for left wall for i in range(nRCoords - 1): mesh.AddSurfaceElement(elements.Element([rPhiToNode[i][0], rPhiToNode[i + 1][0]], leftWallId)) # ... for right wall for i in range(nRCoords - 1): mesh.AddSurfaceElement(elements.Element([rPhiToNode[i][-1], rPhiToNode[i + 1][-1]], rightWallId)) debug.dprint("Finished generating annulus horizontal slice mesh") return mesh
def GenerateCuboidMesh(xCoords, yCoords, zCoords, leftId = 1, rightId = 2, topId = 3, bottomId = 4, frontId = 5, backId = 6, volumeId = 0): """ Generate a structured cuboid mesh """ debug.dprint("Generating cuboid mesh") mesh = meshes.Mesh(3) nXCoords = len(xCoords) nYCoords = len(yCoords) nZCoords = len(zCoords) # Copy and sort the input coords lXCoords = copy.deepcopy(xCoords) lYCoords = copy.deepcopy(yCoords) lZCoords = copy.deepcopy(zCoords) lXCoords.sort() lYCoords.sort() lZCoords.sort() # Generate map from x, y, z IDs to node IDs xyzToNode = [] index = 0 for i in range(nXCoords): xyzToNode.append([]) for j in range(nYCoords): xyzToNode[-1].append([index + i for i in range(nZCoords)]) index += nZCoords # Generate node coordinates for x in lXCoords: for y in lYCoords: for z in lZCoords: mesh.AddNodeCoord([x, y, z]) # Generate volume elements for i in range(nXCoords - 1): debug.dprint("Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint("Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) for k in range(nZCoords - 1): # Out of a hex, construct 6 tets # Construction as in IEEE Transactions on Magnetics, Vol. 26, # No. 2 March 1990 pp. 775-778, Y Tanizume, H Yamashita and # E Nakamae, Fig. 5. a) # Tet 1 mesh.AddVolumeElement(elements.Element([xyzToNode[i + 1][j][k], xyzToNode[i][j][k], xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k]], volumeId)) # Tet 2 mesh.AddVolumeElement(elements.Element([xyzToNode[i + 1][j][k], xyzToNode[i + 1][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j][k + 1]], volumeId)) # Tet 3 mesh.AddVolumeElement(elements.Element([xyzToNode[i + 1][j][k + 1], xyzToNode[i + 1][j + 1][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j][k + 1]], volumeId)) # Tet 4 mesh.AddVolumeElement(elements.Element([xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k + 1], xyzToNode[i + 1][j + 1][k + 1]], volumeId)) # Tet 5 mesh.AddVolumeElement(elements.Element([xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k], xyzToNode[i][j + 1][k + 1]], volumeId)) # Tet 6 mesh.AddVolumeElement(elements.Element([xyzToNode[i][j][k], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k], xyzToNode[i][j][k + 1]], volumeId)) # Generate surface elements ... # ... for left for i in range(nYCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[0][i][j], xyzToNode[0][i][j + 1], xyzToNode[0][i + 1][j]], leftId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[0][i][j + 1], xyzToNode[0][i + 1][j + 1], xyzToNode[0][i + 1][j]], leftId)) # ... for right for i in range(nYCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[-1][i][j], xyzToNode[-1][i][j + 1], xyzToNode[-1][i + 1][j]], rightId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[-1][i][j + 1], xyzToNode[-1][i + 1][j + 1], xyzToNode[-1][i + 1][j]], rightId)) # ... for front for i in range(nXCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[i][0][j], xyzToNode[i + 1][0][j], xyzToNode[i][0][j + 1]], frontId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[i][0][j + 1], xyzToNode[i + 1][0][j], xyzToNode[i + 1][0][j + 1]], frontId)) # ... for back for i in range(nXCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[i][-1][j], xyzToNode[i + 1][-1][j], xyzToNode[i][-1][j + 1]], backId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[i][-1][j + 1], xyzToNode[i + 1][-1][j], xyzToNode[i + 1][-1][j + 1]], backId)) # ... for bottom for i in range(nXCoords - 1): for j in range(nYCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[i][j][0], xyzToNode[i + 1][j][0], xyzToNode[i + 1][j + 1][0]], bottomId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[i][j][0], xyzToNode[i][j + 1][0], xyzToNode[i + 1][j + 1][0]], bottomId)) # ... for top for i in range(nXCoords - 1): for j in range(nYCoords - 1): mesh.AddSurfaceElement(elements.Element([xyzToNode[i][j][-1], xyzToNode[i + 1][j][-1], xyzToNode[i + 1][j + 1][-1]], topId)) mesh.AddSurfaceElement(elements.Element([xyzToNode[i][j][-1], xyzToNode[i][j + 1][-1], xyzToNode[i + 1][j + 1][-1]], topId)) debug.dprint("Finished generating cuboid mesh") return mesh
def GenerateRectangleMesh(xCoords, yCoords, leftId=1, rightId=2, topId=3, bottomId=4, volumeId=0, elementFamilyId=elements.ELEMENT_FAMILY_SIMPLEX): """ Generate a structured 2D linear tet rectangular mesh based upon the given x and y coordinates """ debug.dprint("Generating rectangle mesh") nXCoords = len(xCoords) nYCoords = len(yCoords) # Copy and sort the input coords lXCoords = copy.deepcopy(xCoords) lYCoords = copy.deepcopy(yCoords) lXCoords.sort() lYCoords.sort() # Generate map from x, y IDs to node IDs xyToNode = [] index = 0 for i in range(nXCoords): xyToNode.append([index + i for i in range(nYCoords)]) index += nYCoords mesh = meshes.Mesh(2) # Generate node coordinates for x in lXCoords: for y in lYCoords: mesh.AddNodeCoord([x, y]) if elementFamilyId == elements.ELEMENT_FAMILY_SIMPLEX: # Generate volume elements for i in range(nXCoords - 1): debug.dprint( "Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint( "Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) # Out of a quad, construct 2 triangles # Triangle 1 mesh.AddVolumeElement( elements.Element([ xyToNode[i][j], xyToNode[i + 1][j], xyToNode[i + 1][j + 1] ], volumeId)) # Triangle 2 mesh.AddVolumeElement( elements.Element([ xyToNode[i][j], xyToNode[i + 1][j + 1], xyToNode[i][j + 1] ], volumeId)) elif elementFamilyId == elements.ELEMENT_FAMILY_CUBIC: # Generate volume elements for i in range(nXCoords - 1): debug.dprint( "Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint( "Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) # Quad mesh.AddVolumeElement( elements.Element([ xyToNode[i][j], xyToNode[i + 1][j], xyToNode[i][j + 1], xyToNode[i + 1][j + 1] ], volumeId)) else: raise Exception("Unsupported element family") # Generate surface elements... # ... for left for i in range(nYCoords - 1): mesh.AddSurfaceElement( elements.Element([xyToNode[0][i], xyToNode[0][i + 1]], leftId)) # ... for right for i in range(nYCoords - 1): mesh.AddSurfaceElement( elements.Element([xyToNode[-1][i], xyToNode[-1][i + 1]], rightId)) # ... for bottom for i in range(nXCoords - 1): mesh.AddSurfaceElement( elements.Element([xyToNode[i][0], xyToNode[i + 1][0]], bottomId)) # ... for top for i in range(nXCoords - 1): mesh.AddSurfaceElement( elements.Element([xyToNode[i][-1], xyToNode[i + 1][-1]], topId)) debug.dprint("Finished generating rectangle mesh") return mesh
def GenerateAnnulusHorizontalSliceMesh(rCoords, phiCoords, innerWallId=1, outerWallId=2, leftWallId=5, rightWallId=6, volumeId=0, connectEnds=True): """ Generate a horizontal annulus slice mesh """ debug.dprint("Generating annulus horizonal slice mesh") if connectEnds: debug.dprint("Annulus is connected") else: debug.dprint("Annulus is blocked") # Copy and sort the input coords lRCoords = copy.deepcopy(rCoords) lPhiCoords = copy.deepcopy(phiCoords) lRCoords.sort() lPhiCoords = [] for phi in phiCoords: while phi < 0.0: phi += 2.0 * math.pi while phi > 2.0 * math.pi: phi -= 2.0 * math.pi lPhiCoords.append(phi) lPhiCoords.sort() phiPoints = len(lPhiCoords) if connectEnds: phiDivisions = phiPoints else: phiDivisions = phiPoints - 1 nRCoords = len(rCoords) # Generate map from r, phi IDs to node IDs rPhiToNode = [] index = 0 for i in range(nRCoords): rPhiToNode.append([]) for j in range(phiPoints): rPhiToNode[i].append(index) index += 1 mesh = meshes.Mesh(2) # Generate node coordinates for r in lRCoords: for phi in lPhiCoords: x = r * math.cos(phi) y = r * math.sin(phi) mesh.AddNodeCoord([x, y]) # Generate volume elements for i in range(nRCoords - 1): debug.dprint( "Processing radial element strip " + str(i + 1) + " of " + str(nRCoords - 1), 2) for j in range(phiDivisions): mesh.AddVolumeElement( elements.Element([ rPhiToNode[i][j], rPhiToNode[i + 1][j], rPhiToNode[i][(j + 1) % phiPoints] ], volumeId)) mesh.AddVolumeElement( elements.Element([ rPhiToNode[i + 1][(j + 1) % phiPoints], rPhiToNode[i + 1][j], rPhiToNode[i][(j + 1) % phiPoints] ], volumeId)) # Generate surface elements ... # ... for inner wall for i in range(phiDivisions): mesh.AddSurfaceElement( elements.Element( [rPhiToNode[0][i], rPhiToNode[0][(i + 1) % phiPoints]], innerWallId)) # ... for outer wall for i in range(phiDivisions): mesh.AddSurfaceElement( elements.Element( [rPhiToNode[-1][i], rPhiToNode[-1][(i + 1) % phiPoints]], outerWallId)) if not connectEnds: # ... for left wall for i in range(nRCoords - 1): mesh.AddSurfaceElement( elements.Element([rPhiToNode[i][0], rPhiToNode[i + 1][0]], leftWallId)) # ... for right wall for i in range(nRCoords - 1): mesh.AddSurfaceElement( elements.Element([rPhiToNode[i][-1], rPhiToNode[i + 1][-1]], rightWallId)) debug.dprint("Finished generating annulus horizontal slice mesh") return mesh
def PvtuToVtu(pvtu, model = None, oldNodeIdToNew = [], oldCellIdToNew = [], fieldlist = []): """ Convert a parallel vtu to a serial vtu. Does nothing (except generate a copy) if the supplied vtu is already a serial vtu. """ # Steps 1-5 are now handled by ModelPvtuToVtu (or aren't necessary if # additional information is passed to PvtuToVtu) if((model == None) or (len(oldNodeIdToNew) != pvtu.ugrid.GetNumberOfPoints()) or (len(oldCellIdToNew) != pvtu.ugrid.GetNumberOfCells())): result, oldNodeIdToNew, oldCellIdToNew = ModelPvtuToVtu(pvtu) else: result = model # Step 6: Generate the new point data for i in range(pvtu.ugrid.GetPointData().GetNumberOfArrays()): oldData = pvtu.ugrid.GetPointData().GetArray(i) name = pvtu.ugrid.GetPointData().GetArrayName(i) if len(fieldlist) > 0 and name not in fieldlist: continue debug.dprint("Processing point data " + name) components = oldData.GetNumberOfComponents() tuples = oldData.GetNumberOfTuples() newData = vtk.vtkDoubleArray() newData.SetName(name) newData.SetNumberOfComponents(components) newData.SetNumberOfValues(result.ugrid.GetNumberOfPoints()*components) for nodeId in range(tuples): newNodeId = oldNodeIdToNew[nodeId] if not newNodeId is None: for i in range(components): newData.SetValue(newNodeId * components + i, oldData.GetValue(nodeId * components + i)) result.ugrid.GetPointData().AddArray(newData) # Step 7: Generate the new cell data for i in range(pvtu.ugrid.GetCellData().GetNumberOfArrays()): oldData = pvtu.ugrid.GetCellData().GetArray(i) name = pvtu.ugrid.GetCellData().GetArrayName(i) if len(fieldlist) > 0 and name not in fieldlist: continue debug.dprint("Processing cell data " + name) if name == "vtkGhostLevels": debug.dprint("Skipping ghost level data") continue components = oldData.GetNumberOfComponents() tuples = oldData.GetNumberOfTuples() newData = vtk.vtkDoubleArray() newData.SetName(name) newData.SetNumberOfComponents(components) newData.SetNumberOfValues(result.ugrid.GetNumberOfCells()*components) for cellId in range(tuples): newCellId = oldCellIdToNew[cellId] if not newCellId is None: for i in range(components): newData.SetValue(newCellId * components + i, oldData.GetValue(cellId * components + i)) result.ugrid.GetCellData().AddArray(newData) return result
def PvtuToVtuRemoveDuplicateNodes(pvtu, keepNode): # Detect duplicate nodes and remove them # Jumping through Python 2.3 hoops for cx1 - in >= 2.4, can just pass a cmp # argument to list.sort class LocationSorter(utils.Sorter): def __init__(self, x, y, order = [0, 1, 2]): utils.Sorter.__init__(self, x, y) self._order = order return def __cmp__(self, val): def cmp(x, y, order): for comp in order: if x[comp] > y[comp]: return 1 elif x[comp] < y[comp]: return -1 return 0 return cmp(self._key, val.GetKey(), self._order) def Dup(x, y, tol): for i, xVal in enumerate(x): if abs(xVal - y[i]) > tol: return False return True nodeIds = [] oldNodeIdToNew = [None] * pvtu.ugrid.GetNumberOfPoints() locations = pvtu.GetLocations() lbound, ubound = VtuBoundingBox(pvtu).GetBounds() tol = calc.L2Norm([ubound[i] - lbound[i] for i in range(len(lbound))]) / 1.0e12 debug.dprint("Duplicate node tolerance: " + str(tol)) duplicateNodeMap = [None for i in range(pvtu.ugrid.GetNumberOfPoints())] duplicateNodeMapInverse = [[] for i in range(len(duplicateNodeMap))] # We need to sort the locations using all possible combinations of component # order, to take account of all possible floating point errors. orders = [[0], [[0, 1], [1, 0]], [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]][VtuDim(pvtu) - 1] for order in orders: debug.dprint("Processing component order: " + str(order)) # Generate a sorted list of locations, with their node IDs sortPack = [LocationSorter(location.tolist(), i, order) for i, location in enumerate(locations)] sortPack.sort() permutedLocations = [pack.GetKey() for pack in sortPack] permutedNodeIds = [pack.GetValue() for pack in sortPack] # This rather horrible construction maps all except the first node in each set # of duplicate nodes to the first node in the set of duplicate nodes, for the # sorted current non-ghost locations i = 0 while i < len(permutedLocations) - 1: j = i while j < len(permutedLocations) - 1: if Dup(permutedLocations[i], permutedLocations[j + 1], tol): if keepNode[permutedNodeIds[j + 1]]: oldNodeId = permutedNodeIds[j + 1] newNodeId = permutedNodeIds[i] while not duplicateNodeMap[newNodeId] is None: newNodeId = duplicateNodeMap[newNodeId] if newNodeId == oldNodeId: # This is already mapped the other way break if newNodeId == oldNodeId: # Can only occur from early exit of the above loop j += 1 continue def MapInverses(oldNodeId, newNodeId): for nodeId in duplicateNodeMapInverse[oldNodeId]: assert(not nodeId == newNodeId) assert(keepNode[newNodeId]) keepNode[nodeId] = False duplicateNodeMap[nodeId] = newNodeId duplicateNodeMapInverse[newNodeId].append(nodeId) MapInverses(nodeId, newNodeId) duplicateNodeMapInverse[oldNodeId] = [] return keepNode[newNodeId] = True keepNode[oldNodeId] = False # Map everything mapped to the old node ID to the new node ID MapInverses(oldNodeId, newNodeId) duplicateNodeMap[oldNodeId] = newNodeId duplicateNodeMapInverse[newNodeId].append(oldNodeId) j += 1 else: break i = j i += 1 debug.dprint("Non-ghost nodes: " + str(keepNode.count(True))) # Collect the final non-ghost node IDs and generate the node renumbering map nodeIds = [] index = 0 for i, keep in enumerate(keepNode): if keep: nodeIds.append(i) oldNodeIdToNew[i] = index index += 1 for i, nodeId in enumerate(duplicateNodeMap): if not nodeId is None: assert(oldNodeIdToNew[i] is None) assert(not oldNodeIdToNew[nodeId] is None) oldNodeIdToNew[i] = oldNodeIdToNew[nodeId] debug.dprint("Non-ghost nodes (pass 2): " + str(len(nodeIds))) return oldNodeIdToNew, nodeIds
def ModelPvtuToVtu(pvtu): """ Convert a parallel vtu to a serial vtu but without any fields. Does nothing (except generate a copy) if the supplied vtu is already a serial vtu. """ # Step 1: Extract the ghost levels, and check that we have a parallel vtu result = vtu() ghostLevel = pvtu.ugrid.GetCellData().GetArray("vtkGhostLevels") if ghostLevel is None: # We have a serial vtu debug.deprint("Warning: input file contains no vtkGhostLevels") ghostLevel = [0 for i in range(pvtu.ugrid.GetNumberOfCells())] else: # We have a parallel vtu ghostLevel = [ghostLevel.GetValue(i) for i in range(ghostLevel.GetNumberOfComponents() * ghostLevel.GetNumberOfTuples())] # Step 2: Collect the non-ghost cell IDs debug.dprint("Input cells: " + str(pvtu.ugrid.GetNumberOfCells())) cellIds = [] keepCell = [False for i in range(pvtu.ugrid.GetNumberOfCells())] oldCellIdToNew = [None for i in range(pvtu.ugrid.GetNumberOfCells())] # Collect the new non-ghost cell IDs and generate the cell renumbering map index = 0 for i, level in enumerate(ghostLevel): if calc.AlmostEquals(level, 0.0): cellIds.append(i) keepCell[i] = True oldCellIdToNew[i] = index index += 1 debug.dprint("Non-ghost cells: " + str(len(cellIds))) # Step 3: Collect the non-ghost node IDs debug.dprint("Input points: " + str(pvtu.ugrid.GetNumberOfPoints())) keepNode = [False for i in range(pvtu.ugrid.GetNumberOfPoints())] # Find a list of candidate non-ghost node IDs, based on nodes attached to # non-ghost cells keepNodeCount = 0 for cellId in cellIds: cellNodeIds = pvtu.ugrid.GetCell(cellId).GetPointIds() cellNodeIds = [cellNodeIds.GetId(i) for i in range(cellNodeIds.GetNumberOfIds())] keepNodeCount += len(cellNodeIds) for nodeId in cellNodeIds: keepNode[nodeId] = True uniqueKeepNodeCount = keepNode.count(True) debug.dprint("Non-ghost nodes (pass 1): " + str(uniqueKeepNodeCount)) if uniqueKeepNodeCount==keepNodeCount: debug.dprint("Assuming pvtu is discontinuous") # we're keeping all non-ghost nodes: nodeIds = [i for i in range(pvtu.ugrid.GetNumberOfPoints()) if keepNode[i]] oldNodeIdToNew = numpy.array([None]*pvtu.ugrid.GetNumberOfPoints()) oldNodeIdToNew[nodeIds] = range(keepNodeCount) else: # for the CG case we still have duplicate nodes that need to be removed oldNodeIdToNew, nodeIds = PvtuToVtuRemoveDuplicateNodes(pvtu, keepNode) # Step 4: Generate the new locations locations = pvtu.GetLocations() locations = numpy.array([locations[i] for i in nodeIds]) points = vtk.vtkPoints() points.SetDataTypeToDouble() for location in locations: points.InsertNextPoint(location) result.ugrid.SetPoints(points) # Step 5: Generate the new cells for cellId in cellIds: cell = pvtu.ugrid.GetCell(cellId) cellNodeIds = cell.GetPointIds() cellNodeIds = [cellNodeIds.GetId(i) for i in range(cellNodeIds.GetNumberOfIds())] idList = vtk.vtkIdList() for nodeId in cellNodeIds: oldNodeId = nodeId nodeId = oldNodeIdToNew[nodeId] assert(not nodeId is None) assert(nodeId >= 0) assert(nodeId <= len(nodeIds)) idList.InsertNextId(nodeId) result.ugrid.InsertNextCell(cell.GetCellType(), idList) return result, oldNodeIdToNew, oldCellIdToNew
def ModelPvtuToVtu(pvtu): """ Convert a parallel vtu to a serial vtu but without any fields. Does nothing (except generate a copy) if the supplied vtu is already a serial vtu. """ # Step 1: Extract the ghost levels, and check that we have a parallel vtu result = vtu() ghostLevel = pvtu.ugrid.GetCellData().GetArray("vtkGhostLevels") if ghostLevel is None: # We have a serial vtu debug.deprint("Warning: VtuFromPvtu passed a serial vtu") ghostLevel = [0 for i in range(vtu.ugrid.GetNumberOfCells())] else: # We have a parallel vtu ghostLevel = [ ghostLevel.GetValue(i) for i in range(ghostLevel.GetNumberOfComponents() * ghostLevel.GetNumberOfTuples()) ] # Step 2: Collect the non-ghost cell IDs debug.dprint("Input cells: " + str(pvtu.ugrid.GetNumberOfCells())) cellIds = [] keepCell = [False for i in range(pvtu.ugrid.GetNumberOfCells())] oldCellIdToNew = [None for i in range(pvtu.ugrid.GetNumberOfCells())] # Collect the new non-ghost cell IDs and generate the cell renumbering map index = 0 for i, level in enumerate(ghostLevel): if calc.AlmostEquals(level, 0.0): cellIds.append(i) keepCell[i] = True oldCellIdToNew[i] = index index += 1 debug.dprint("Non-ghost cells: " + str(len(cellIds))) # Step 3: Collect the non-ghost node IDs debug.dprint("Input points: " + str(pvtu.ugrid.GetNumberOfPoints())) nodeIds = [] keepNode = [False for i in range(pvtu.ugrid.GetNumberOfPoints())] oldNodeIdToNew = [None for i in range(pvtu.ugrid.GetNumberOfPoints())] # Find a list of candidate non-ghost node IDs, based on nodes attached to # non-ghost cells for cellId in cellIds: cellNodeIds = pvtu.ugrid.GetCell(cellId).GetPointIds() cellNodeIds = [ cellNodeIds.GetId(i) for i in range(cellNodeIds.GetNumberOfIds()) ] for nodeId in cellNodeIds: keepNode[nodeId] = True debug.dprint("Non-ghost nodes (pass 1): " + str(keepNode.count(True))) # Detect duplicate nodes # Jumping through Python 2.3 hoops for cx1 - in >= 2.4, can just pass a cmp # argument to list.sort class LocationSorter(utils.Sorter): def __init__(self, x, y, order=[0, 1, 2]): utils.Sorter.__init__(self, x, y) self._order = order return def __cmp__(self, val): def cmp(x, y, order): for comp in order: if x[comp] > y[comp]: return 1 elif x[comp] < y[comp]: return -1 return 0 return cmp(self._key, val.GetKey(), self._order) def Dup(x, y, tol): for i, xVal in enumerate(x): if abs(xVal - y[i]) > tol: return False return True locations = pvtu.GetLocations() lbound, ubound = VtuBoundingBox(pvtu).GetBounds() tol = calc.L2Norm([ubound[i] - lbound[i] for i in range(len(lbound))]) / 1.0e12 debug.dprint("Duplicate node tolerance: " + str(tol)) duplicateNodeMap = [None for i in range(pvtu.ugrid.GetNumberOfPoints())] duplicateNodeMapInverse = [[] for i in range(len(duplicateNodeMap))] # We need to sort the locations using all possible combinations of component # order, to take account of all possible floating point errors. orders = [[0], [[0, 1], [1, 0]], [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]][VtuDim(pvtu) - 1] for order in orders: debug.dprint("Processing component order: " + str(order)) # Generate a sorted list of locations, with their node IDs sortPack = [ LocationSorter(location.tolist(), i, order) for i, location in enumerate(locations) ] sortPack.sort() permutedLocations = [pack.GetKey() for pack in sortPack] permutedNodeIds = [pack.GetValue() for pack in sortPack] # This rather horrible construction maps all except the first node in each set # of duplicate nodes to the first node in the set of duplicate nodes, for the # sorted current non-ghost locations i = 0 while i < len(permutedLocations) - 1: j = i while j < len(permutedLocations) - 1: if Dup(permutedLocations[i], permutedLocations[j + 1], tol): if keepNode[permutedNodeIds[j + 1]]: oldNodeId = permutedNodeIds[j + 1] newNodeId = permutedNodeIds[i] while not duplicateNodeMap[newNodeId] is None: newNodeId = duplicateNodeMap[newNodeId] if newNodeId == oldNodeId: # This is already mapped the other way break if newNodeId == oldNodeId: # Can only occur from early exit of the above loop j += 1 continue def MapInverses(oldNodeId, newNodeId): for nodeId in duplicateNodeMapInverse[oldNodeId]: assert (not nodeId == newNodeId) assert (keepNode[newNodeId]) keepNode[nodeId] = False duplicateNodeMap[nodeId] = newNodeId duplicateNodeMapInverse[newNodeId].append( nodeId) MapInverses(nodeId, newNodeId) duplicateNodeMapInverse[oldNodeId] = [] return keepNode[newNodeId] = True keepNode[oldNodeId] = False # Map everything mapped to the old node ID to the new node ID MapInverses(oldNodeId, newNodeId) duplicateNodeMap[oldNodeId] = newNodeId duplicateNodeMapInverse[newNodeId].append(oldNodeId) j += 1 else: break i = j i += 1 debug.dprint("Non-ghost nodes: " + str(keepNode.count(True))) # Collect the final non-ghost node IDs and generate the node renumbering map nodeIds = [] index = 0 for i, keep in enumerate(keepNode): if keep: nodeIds.append(i) oldNodeIdToNew[i] = index index += 1 for i, nodeId in enumerate(duplicateNodeMap): if not nodeId is None: assert (oldNodeIdToNew[i] is None) assert (not oldNodeIdToNew[nodeId] is None) oldNodeIdToNew[i] = oldNodeIdToNew[nodeId] debug.dprint("Non-ghost nodes (pass 2): " + str(len(nodeIds))) # Step 4: Generate the new locations locations = pvtu.GetLocations() locations = numpy.array([locations[i] for i in nodeIds]) points = vtk.vtkPoints() points.SetDataTypeToDouble() for location in locations: points.InsertNextPoint(location) result.ugrid.SetPoints(points) # Step 5: Generate the new cells for cellId in cellIds: cell = pvtu.ugrid.GetCell(cellId) cellNodeIds = cell.GetPointIds() cellNodeIds = [ cellNodeIds.GetId(i) for i in range(cellNodeIds.GetNumberOfIds()) ] idList = vtk.vtkIdList() for nodeId in cellNodeIds: oldNodeId = nodeId nodeId = oldNodeIdToNew[nodeId] assert (not nodeId is None) assert (nodeId >= 0) assert (nodeId <= len(nodeIds)) idList.InsertNextId(nodeId) result.ugrid.InsertNextCell(cell.GetCellType(), idList) return result, oldNodeIdToNew, oldCellIdToNew
def PrintVtu(vtu, debugLevel = 0): """ Print the supplied vtu """ debug.dprint("Filename: " + str(vtu.filename), debugLevel) debug.dprint("Dimension: " + str(VtuDim(vtu)), debugLevel) debug.dprint("Bounding box: " + str(VtuBoundingBox(vtu)), debugLevel) debug.dprint("Nodes: " + str(vtu.ugrid.GetNumberOfPoints()), debugLevel) debug.dprint("Elements: " + str(vtu.ugrid.GetNumberOfCells()), debugLevel) debug.dprint("Fields: " + str(len(vtu.GetFieldNames())), debugLevel) for fieldName in vtu.GetFieldNames(): string = fieldName + ", " rank = VtuFieldRank(vtu, fieldName) if rank == 0: string += "scalar" elif rank == 1: string += "vector" elif rank == 2: string += "tensor" else: string += "unknown" string += " field with shape " + str(VtuFieldShape(vtu, fieldName)) debug.dprint(string, debugLevel) debug.dprint("Cell fields: " + str(len(VtuGetCellFieldNames(vtu))), debugLevel) for fieldName in VtuGetCellFieldNames(vtu): string = fieldName debug.dprint(string, debugLevel) return
def TimeAveragedVtu(filenames, timeFieldName = "Time", baseMesh = None, baseVtu = None): """ Perform a time weighted average of vtus with the supplied filenames. The filenames must be in time order. """ debug.dprint("Computing time averaged vtu") if not baseMesh is None: assert(baseVtu is None) result = baseMesh.ToVtu() elif not baseVtu is None: assert(baseMesh is None) result = CopyVtu(baseVtu) else: result = None if len(filenames) == 0: if result is None: return vtu() else: return result startTime = None finalTime = None lastDt = None nextInputVtu = None for i, filename in enumerate(filenames): debug.dprint("Processing file " + filename) if nextInputVtu is None: inputVtu = vtu(filename) else: inputVtu = nextInputVtu if result is None: result = vtu() # Add the points result.ugrid.SetPoints(inputVtu.ugrid.GetPoints()) # Add the cells result.ugrid.SetCells(inputVtu.ugrid.GetCellTypesArray(), inputVtu.ugrid.GetCellLocationsArray(), inputVtu.ugrid.GetCells()) if len(filenames) == 1: weight = 1.0 else: # Trapezium rule weighting weight = 0.0 if not lastDt is None: weight += lastDt timeField = inputVtu.GetScalarField(timeFieldName) assert(len(timeField) > 0) if startTime is None: startTime = timeField[0] if i < len(filenames) - 1: nextInputVtu = vtu(filenames[i + 1]) nextTimeField = nextInputVtu.GetScalarField(timeFieldName) assert(len(nextTimeField) > 0) if finalTime is None: finalTime = nextTimeField[0] dt = nextTimeField[0] - timeField[0] lastDt = dt weight += dt weight /= 2.0 debug.dprint("weight = " + str(weight)) if i == 0: if not VtuMatchLocations(inputVtu, result): inputVtu = RemappedVtu(inputVtu, result) for fieldName in inputVtu.GetFieldNames(): result.AddField(fieldName, inputVtu.GetField(fieldName) * weight) else: AddtoVtu(result, inputVtu, scale = weight) if len(filenames) > 1: debug.dprint("Start time = " + str(startTime)) debug.dprint("Final time = " + str(finalTime)) DivideVtu(result, finalTime - startTime) debug.dprint("Finished computing time averaged vtu") return result
def PvtuToVtu(pvtu, model=None, oldNodeIdToNew=[], oldCellIdToNew=[], fieldlist=[]): """ Convert a parallel vtu to a serial vtu. Does nothing (except generate a copy) if the supplied vtu is already a serial vtu. """ # Steps 1-5 are now handled by ModelPvtuToVtu (or aren't necessary if # additional information is passed to PvtuToVtu) if ((model == None) or (len(oldNodeIdToNew) != pvtu.ugrid.GetNumberOfPoints()) or (len(oldCellIdToNew) != pvtu.ugrid.GetNumberOfCells())): result, oldNodeIdToNew, oldCellIdToNew = ModelPvtuToVtu(pvtu) else: result = model # Step 6: Generate the new point data for i in range(pvtu.ugrid.GetPointData().GetNumberOfArrays()): oldData = pvtu.ugrid.GetPointData().GetArray(i) name = pvtu.ugrid.GetPointData().GetArrayName(i) if len(fieldlist) > 0 and name not in fieldlist: continue debug.dprint("Processing point data " + name) components = oldData.GetNumberOfComponents() tuples = oldData.GetNumberOfTuples() newData = vtk.vtkDoubleArray() newData.SetName(name) newData.SetNumberOfComponents(components) newData.SetNumberOfValues(result.ugrid.GetNumberOfPoints() * components) for nodeId in range(tuples): newNodeId = oldNodeIdToNew[nodeId] if not newNodeId is None: for i in range(components): newData.SetValue(newNodeId * components + i, oldData.GetValue(nodeId * components + i)) result.ugrid.GetPointData().AddArray(newData) # Step 7: Generate the new cell data for i in range(pvtu.ugrid.GetCellData().GetNumberOfArrays()): oldData = pvtu.ugrid.GetCellData().GetArray(i) name = pvtu.ugrid.GetCellData().GetArrayName(i) if len(fieldlist) > 0 and name not in fieldlist: continue debug.dprint("Processing cell data " + name) if name == "vtkGhostLevels": debug.dprint("Skipping ghost level data") continue components = oldData.GetNumberOfComponents() tuples = oldData.GetNumberOfTuples() newData = vtk.vtkDoubleArray() newData.SetName(name) newData.SetNumberOfComponents(components) newData.SetNumberOfValues(result.ugrid.GetNumberOfCells() * components) for cellId in range(tuples): newCellId = oldCellIdToNew[cellId] if not newCellId is None: for i in range(components): newData.SetValue(newCellId * components + i, oldData.GetValue(cellId * components + i)) result.ugrid.GetCellData().AddArray(newData) return result
def ReadMsh(filename): """ Read a Gmsh msh file """ def ReadNonCommentLine(fileHandle): line = fileHandle.readline().decode("utf8") while len(line) > 0: line = line.strip() if len(line) > 0: return line line = fileHandle.readline().decode("utf8") return line fileHandle = open(filename, "rb") basename = filename.split(".")[0] hasHalo = filehandling.FileExists(basename + ".halo") # Read the MeshFormat section line = ReadNonCommentLine(fileHandle) assert(line == "$MeshFormat") line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) == 3) version = float(lineSplit[0]) fileType = int(lineSplit[1]) dataSize = int(lineSplit[2]) if fileType == 1: # Binary format if dataSize == 4: realFormat = "f" elif dataSize == 8: realFormat = "d" else: raise Exception("Unrecognised real size " + str(dataSize)) iArr = array.array("i") iArr.fromfile(fileHandle, 1) if iArr[0] == 1: swap = False else: iArr.byteswap() if iArr[0] == 1: swap = True else: raise Exception("Invalid one byte") line = ReadNonCommentLine(fileHandle) assert(line == "$EndMeshFormat") # Read the Nodes section line = ReadNonCommentLine(fileHandle) assert(line == "$Nodes") line = ReadNonCommentLine(fileHandle) nNodes = int(line) # Assume dense node IDs, but not necessarily ordered seenNode = [False for i in range(nNodes)] nodeIds = [] nodes = [] lbound = [calc.Inf() for i in range(3)] ubound = [-calc.Inf() for i in range(3)] for i in range(nNodes): iArr = array.array("i") rArr = array.array(realFormat) iArr.fromfile(fileHandle, 1) rArr.fromfile(fileHandle, 3) if swap: iArr.byteswap() rArr.byteswap() nodeId = iArr[0] coord = rArr assert(nodeId > 0) assert(not seenNode[nodeId - 1]) seenNode[nodeId - 1] = True nodeIds.append(nodeId) nodes.append(coord) for j in range(3): lbound[j] = min(lbound[j], coord[j]) ubound[j] = max(ubound[j], coord[j]) line = ReadNonCommentLine(fileHandle) assert(line == "$EndNodes") nodes = utils.KeyedSort(nodeIds, nodes) bound = bounds.BoundingBox(lbound, ubound) indices = bound.UsedDimIndices() dim = len(indices) if dim < 3: nodes = [[coord[index] for index in indices] for coord in nodes] mesh = meshes.Mesh(dim) mesh.AddNodeCoords(nodes) # Read the Elements section line = ReadNonCommentLine(fileHandle) assert(line == "$Elements") line = ReadNonCommentLine(fileHandle) nEles = int(line) i = 0 while i < nEles: iArr = array.array("i") iArr.fromfile(fileHandle, 3) if swap: iArr.byteswap() typeId = iArr[0] nSubEles = iArr[1] nIds = iArr[2] type = GmshElementType(gmshElementTypeId = typeId) for j in range(nSubEles): iArr = array.array("i") iArr.fromfile(fileHandle, 1 + nIds + type.GetNodeCount()) if swap: iArr.byteswap() eleId = iArr[0] assert(eleId > 0) ids = iArr[1:1 + nIds] nodes = FromGmshNodeOrder(utils.OffsetList(iArr[-type.GetNodeCount():], -1), type) element = elements.Element(nodes, ids) if type.GetDim() == dim - 1: mesh.AddSurfaceElement(element) elif type.GetDim() == dim: mesh.AddVolumeElement(element) else: debug.deprint("Warning: Element of type " + str(type) + " encountered in " + str(dim) + " dimensions") i += nSubEles assert(i == nEles) line = ReadNonCommentLine(fileHandle) assert(line == "$EndElements") elif fileType == 0: # ASCII format line = ReadNonCommentLine(fileHandle) assert(line == "$EndMeshFormat") # Read the Nodes section line = ReadNonCommentLine(fileHandle) assert(line == "$Nodes") line = ReadNonCommentLine(fileHandle) nNodes = int(line) # Assume dense node IDs, but not necessarily ordered seenNode = [False for i in range(nNodes)] nodeIds = [] nodes = [] lbound = [calc.Inf() for i in range(3)] ubound = [-calc.Inf() for i in range(3)] for i in range(nNodes): line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) == 4) nodeId = int(lineSplit[0]) coord = [float(comp) for comp in lineSplit[1:]] assert(nodeId > 0) assert(not seenNode[nodeId - 1]) seenNode[nodeId - 1] = True nodeIds.append(nodeId) nodes.append(coord) for j in range(3): lbound[j] = min(lbound[j], coord[j]) ubound[j] = max(ubound[j], coord[j]) line = ReadNonCommentLine(fileHandle) assert(line == "$EndNodes") nodes = utils.KeyedSort(nodeIds, nodes) bound = bounds.BoundingBox(lbound, ubound) indices = bound.UsedDimIndices() dim = len(indices) if dim < 3: nodes = [[coord[index] for index in indices] for coord in nodes] mesh = meshes.Mesh(dim) mesh.AddNodeCoords(nodes) # Read the Elements section line = ReadNonCommentLine(fileHandle) assert(line == "$Elements") line = ReadNonCommentLine(fileHandle) nEles = int(line) for i in range(nEles): line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) > 3) eleId = int(lineSplit[0]) assert(eleId > 0) typeId = int(lineSplit[1]) nIds = int(lineSplit[2]) type = GmshElementType(gmshElementTypeId = typeId) ids = [int(id) for id in lineSplit[3:3 + nIds]] nodes = FromGmshNodeOrder([int(node) - 1 for node in lineSplit[-type.GetNodeCount():]], type) element = elements.Element(nodes, ids) if type.GetDim() == dim - 1: mesh.AddSurfaceElement(element) elif type.GetDim() == dim: mesh.AddVolumeElement(element) else: debug.deprint("Warning: Element of type " + str(type) + " encountered in " + str(dim) + " dimensions") line = ReadNonCommentLine(fileHandle) assert(line == "$EndElements") # Ignore all remaining sections else: raise Exception("File type " + str(fileType) + " not recognised") fileHandle.close() if hasHalo: # Read the .halo file debug.dprint("Reading .halo file") if mesh_halos.HaloIOSupport(): halos = mesh_halos.ReadHalos(basename + ".halo") mesh.SetHalos(halos) else: debug.deprint("Warning: No .halo I/O support") return mesh
def GenerateAnnulusMesh(rCoords, zCoords, phiCoords, innerWallId=1, outerWallId=2, topId=3, bottomId=4, leftWallId=5, rightWallId=6, volumeId=0, connectEnds=True): """ Generate a structured 3D linear tet annulus mesh based upon the given r and z phi coordinates """ debug.dprint("Generating annulus mesh") if connectEnds: debug.dprint("Annulus is connected") else: debug.dprint("Annulus is blocked") # Copy and sort the input coords lRCoords = copy.deepcopy(rCoords) lZCoords = copy.deepcopy(zCoords) lPhiCoords = copy.deepcopy(phiCoords) lRCoords.sort() lZCoords.sort() lPhiCoords = [] for phi in phiCoords: while phi < 0.0: phi += 2.0 * math.pi while phi > 2.0 * math.pi: phi -= 2.0 * math.pi lPhiCoords.append(phi) lPhiCoords.sort() phiPoints = len(lPhiCoords) if connectEnds: phiDivisions = phiPoints else: phiDivisions = phiPoints - 1 nRCoords = len(rCoords) nZCoords = len(zCoords) # Generate map from r, z, phi IDs to node IDs rzphiToNode = GenerateAnnulusRZPhiToNode(nRCoords, nZCoords, phiPoints) mesh = meshes.Mesh(3) # Generate node coordinates for r in lRCoords: for z in lZCoords: for phi in lPhiCoords: x = r * math.cos(phi) y = r * math.sin(phi) mesh.AddNodeCoord([x, y, z]) # Generate volume elements for i in range(nRCoords - 1): debug.dprint( "Processing radial element strip " + str(i + 1) + " of " + str(nRCoords - 1), 2) for j in range(nZCoords - 1): debug.dprint( "Processing vertical element loop " + str(j + 1) + " of " + str(nZCoords - 1), 3) for k in range(phiDivisions): # Out of a hex, construct 6 tets # Construction as in IEEE Transactions on Magnetics, Vol. 26, # No. 2 March 1990 pp. 775-778, Y Tanizume, H Yamashita and # E Nakamae, Fig. 5. a) # Tet 1 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i + 1][j][k], rzphiToNode[i][j][k], rzphiToNode[i + 1][j + 1][k], rzphiToNode[i][j][(k + 1) % phiPoints] ], volumeId)) # Tet 2 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i + 1][j][k], rzphiToNode[i + 1][j][(k + 1) % phiPoints], rzphiToNode[i][j][(k + 1) % phiPoints], rzphiToNode[i + 1][j + 1][k] ], volumeId)) # Tet 3 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i + 1][j][(k + 1) % phiPoints], rzphiToNode[i + 1][j + 1][(k + 1) % phiPoints], rzphiToNode[i][j][(k + 1) % phiPoints], rzphiToNode[i + 1][j + 1][k] ], volumeId)) # Tet 4 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i][j][(k + 1) % phiPoints], rzphiToNode[i + 1][j + 1][k], rzphiToNode[i + 1][j + 1][(k + 1) % phiPoints], rzphiToNode[i][j + 1][(k + 1) % phiPoints] ], volumeId)) # Tet 5 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i][j][(k + 1) % phiPoints], rzphiToNode[i + 1][j + 1][k], rzphiToNode[i][j + 1][(k + 1) % phiPoints], rzphiToNode[i][j + 1][k] ], volumeId)) # Tet 6 mesh.AddVolumeElement( elements.Element([ rzphiToNode[i][j][k], rzphiToNode[i + 1][j + 1][k], rzphiToNode[i][j][(k + 1) % phiPoints], rzphiToNode[i][j + 1][k] ], volumeId)) # Generate surface elements ... # ... for inner wall for i in range(nZCoords - 1): for j in range(phiDivisions): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[0][i][j], rzphiToNode[0][i][(j + 1) % phiPoints], rzphiToNode[0][i + 1][j] ], innerWallId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[0][i][(j + 1) % phiPoints], rzphiToNode[0][i + 1][(j + 1) % phiPoints], rzphiToNode[0][i + 1][j] ], innerWallId)) # ... for outer wall for i in range(nZCoords - 1): for j in range(phiDivisions): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[-1][i][j], rzphiToNode[-1][i][(j + 1) % phiPoints], rzphiToNode[-1][i + 1][j] ], outerWallId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[-1][i][(j + 1) % phiPoints], rzphiToNode[-1][i + 1][(j + 1) % phiPoints], rzphiToNode[-1][i + 1][j] ], outerWallId)) # ... for top for i in range(nRCoords - 1): for j in range(phiDivisions): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][-1][j], rzphiToNode[i + 1][-1][j], rzphiToNode[i][-1][(j + 1) % phiPoints] ], topId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][-1][(j + 1) % phiPoints], rzphiToNode[i + 1][-1][j], rzphiToNode[i + 1][-1][(j + 1) % phiPoints] ], topId)) # ... for bottom for i in range(nRCoords - 1): for j in range(phiDivisions): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][0][j], rzphiToNode[i + 1][0][j], rzphiToNode[i][0][(j + 1) % phiPoints] ], bottomId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][0][(j + 1) % phiPoints], rzphiToNode[i + 1][0][j], rzphiToNode[i + 1][0][(j + 1) % phiPoints] ], bottomId)) if not connectEnds: # ... for left wall for i in range(nRCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][j][0], rzphiToNode[i + 1][j][0], rzphiToNode[i + 1][j + 1][0] ], leftWallId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][j][0], rzphiToNode[i][j + 1][0], rzphiToNode[i + 1][j + 1][0] ], leftWallId)) # ... for right wall for i in range(nRCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][j][-1], rzphiToNode[i + 1][j][-1], rzphiToNode[i + 1][j + 1][-1] ], rightWallId)) mesh.AddSurfaceElement( elements.Element([ rzphiToNode[i][j][-1], rzphiToNode[i][j + 1][-1], rzphiToNode[i + 1][j + 1][-1] ], rightWallId)) debug.dprint("Finished generating annulus mesh") return mesh
def LineVtuCut(inputVtu, origin = (0.0, 0.0, 0.0), direction = (1.0, 0.0, 0.0)): """ Perform a plane-plane double cut to form a 1D line (in 3D space) """ assert(len(origin) == 3) assert(len(direction) == 3) # Copy the input line direction x0 = direction[0] y0 = direction[1] z0 = direction[2] # To form the line from two planar cuts, we need two normal vectors at right # angles to the line direction. # Form the first normal vector by imposing x0 dot x1 = 0, with one component # of x1 equal to one and one equal to zero, where the component in x0 # corresponding to the remaining third component is non-zero if calc.AlmostEquals(z0, 0.0): if calc.AlmostEquals(y0, 0.0): if calc.AlmostEquals(x0, 0.0): raise Exception("Direction has zero length") y1 = 1.0 z1 = 0.0 # x1 = -(y0 y1 + z0 z1) / x0 x1 = -y0 / x0 else: x1 = 1.0 z1 = 0.0 # y1 = -(x0 x1 + z0 z1) / y0 y1 = - x0 / y0 else: x1 = 1.0 y1 = 0.0 # z1 = -(x0 x1 + y0 y1) / z0 z1 = - x0 / z0 # Normalise the first normal vector mag = calc.L2Norm([x1, y1, z1]) x1 /= mag y1 /= mag z1 /= mag # Form the second normal vector via a cross product x2 = y0 * z1 - z0 * y1 y2 = z0 * x1 - x0 * z1 z2 = x0 * y1 - y0 * x1 # Normalise the second normal vector mag = calc.L2Norm([x2, y2, z2]) x2 /= mag y2 /= mag z2 /= mag normal1 = (x1, y1, z1) normal2 = (x2, y2, z2) debug.dprint("Normal 1 = " + str(normal1)) debug.dprint("Normal 2 = " + str(normal2)) # Perform the cuts cutVtu = PlanarVtuCut(inputVtu, origin, normal1) cutVtu = PlanarVtuCut(cutVtu, origin, normal2) return cutVtu
if len(args) < 2: debug.FatalError("GMSH base name and vtu name required") elif len(args) > 2: debug.FatalError("Unrecognised trailing argument") meshBasename = args[0] vtuFilename = args[1] possibleMeshBasenames = glob.glob(meshBasename + "_?*.msh") meshBasenames = [] meshIds = [] for possibleMeshBasename in possibleMeshBasenames: id = possibleMeshBasename[len(meshBasename) + 1:-4] try: id = int(id) except ValueError: continue meshBasenames.append(possibleMeshBasename[:-4]) meshIds.append(id) vtuBasename = os.path.basename(vtuFilename[:-len(vtuFilename.split(".")[-1]) - 1]) vtuExt = vtuFilename[-len(vtuFilename.split(".")[-1]):] vtu = vtktools.vtu(vtuFilename) for i, meshBasename in enumerate(meshBasenames): debug.dprint("Processing mesh partition " + meshBasename) meshVtu = gmshtools.ReadMsh(meshBasename).ToVtu(includeSurface = False) partition = vtktools.RemappedVtu(vtu, meshVtu) partition.Write(vtuBasename + "_" + str(meshIds[i]) + "." + vtuExt)
if len(args) > 3: debug.FatalError("Unrecognised trailing argument") inputProject = args[0] if len(args) == 2: try: firstId = int(args[1]) lastId = firstId except ValueError: debug.FatalError("Invalid first dump ID") if len(args) == 3: try: firstId = int(args[1]) lastId = int(args[2]) assert(lastId >= firstId) except: debug.FatalError("Invalid last dump ID") if len(args) == 1: filenames = [inputProject + ".pvtu"] else: filenames = fluidity_tools.VtuFilenames(inputProject, firstId, lastId = lastId, extension = ".pvtu") for filename in filenames: debug.dprint("Processing file: " + filename) vtu = vtktools.vtu(filename) vtu = vtktools.VtuFromPvtu(vtu) vtu.Write(filename[:-5] + ".vtu")
def GenerateCuboidMesh(xCoords, yCoords, zCoords, leftId=1, rightId=2, topId=3, bottomId=4, frontId=5, backId=6, volumeId=0): """ Generate a structured cuboid mesh """ debug.dprint("Generating cuboid mesh") mesh = meshes.Mesh(3) nXCoords = len(xCoords) nYCoords = len(yCoords) nZCoords = len(zCoords) # Copy and sort the input coords lXCoords = copy.deepcopy(xCoords) lYCoords = copy.deepcopy(yCoords) lZCoords = copy.deepcopy(zCoords) lXCoords.sort() lYCoords.sort() lZCoords.sort() # Generate map from x, y, z IDs to node IDs xyzToNode = [] index = 0 for i in range(nXCoords): xyzToNode.append([]) for j in range(nYCoords): xyzToNode[-1].append([index + i for i in range(nZCoords)]) index += nZCoords # Generate node coordinates for x in lXCoords: for y in lYCoords: for z in lZCoords: mesh.AddNodeCoord([x, y, z]) # Generate volume elements for i in range(nXCoords - 1): debug.dprint( "Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint( "Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) for k in range(nZCoords - 1): # Out of a hex, construct 6 tets # Construction as in IEEE Transactions on Magnetics, Vol. 26, # No. 2 March 1990 pp. 775-778, Y Tanizume, H Yamashita and # E Nakamae, Fig. 5. a) # Tet 1 mesh.AddVolumeElement( elements.Element([ xyzToNode[i + 1][j][k], xyzToNode[i][j][k], xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k] ], volumeId)) # Tet 2 mesh.AddVolumeElement( elements.Element([ xyzToNode[i + 1][j][k], xyzToNode[i + 1][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j][k + 1] ], volumeId)) # Tet 3 mesh.AddVolumeElement( elements.Element([ xyzToNode[i + 1][j][k + 1], xyzToNode[i + 1][j + 1][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j][k + 1] ], volumeId)) # Tet 4 mesh.AddVolumeElement( elements.Element([ xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k + 1], xyzToNode[i + 1][j + 1][k + 1] ], volumeId)) # Tet 5 mesh.AddVolumeElement( elements.Element([ xyzToNode[i][j][k + 1], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k], xyzToNode[i][j + 1][k + 1] ], volumeId)) # Tet 6 mesh.AddVolumeElement( elements.Element([ xyzToNode[i][j][k], xyzToNode[i + 1][j + 1][k], xyzToNode[i][j + 1][k], xyzToNode[i][j][k + 1] ], volumeId)) # Generate surface elements ... # ... for left for i in range(nYCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[0][i][j], xyzToNode[0][i][j + 1], xyzToNode[0][i + 1][j] ], leftId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[0][i][j + 1], xyzToNode[0][i + 1][j + 1], xyzToNode[0][i + 1][j] ], leftId)) # ... for right for i in range(nYCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[-1][i][j], xyzToNode[-1][i][j + 1], xyzToNode[-1][i + 1][j] ], rightId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[-1][i][j + 1], xyzToNode[-1][i + 1][j + 1], xyzToNode[-1][i + 1][j] ], rightId)) # ... for front for i in range(nXCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][0][j], xyzToNode[i + 1][0][j], xyzToNode[i][0][j + 1] ], frontId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][0][j + 1], xyzToNode[i + 1][0][j], xyzToNode[i + 1][0][j + 1] ], frontId)) # ... for back for i in range(nXCoords - 1): for j in range(nZCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][-1][j], xyzToNode[i + 1][-1][j], xyzToNode[i][-1][j + 1] ], backId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][-1][j + 1], xyzToNode[i + 1][-1][j], xyzToNode[i + 1][-1][j + 1] ], backId)) # ... for bottom for i in range(nXCoords - 1): for j in range(nYCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][j][0], xyzToNode[i + 1][j][0], xyzToNode[i + 1][j + 1][0] ], bottomId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][j][0], xyzToNode[i][j + 1][0], xyzToNode[i + 1][j + 1][0] ], bottomId)) # ... for top for i in range(nXCoords - 1): for j in range(nYCoords - 1): mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][j][-1], xyzToNode[i + 1][j][-1], xyzToNode[i + 1][j + 1][-1] ], topId)) mesh.AddSurfaceElement( elements.Element([ xyzToNode[i][j][-1], xyzToNode[i][j + 1][-1], xyzToNode[i + 1][j + 1][-1] ], topId)) debug.dprint("Finished generating cuboid mesh") return mesh
def PrintVtu(vtu, debugLevel=0): """ Print the supplied vtu """ debug.dprint("Filename: " + str(vtu.filename), debugLevel) debug.dprint("Dimension: " + str(VtuDim(vtu)), debugLevel) debug.dprint("Bounding box: " + str(VtuBoundingBox(vtu)), debugLevel) debug.dprint("Nodes: " + str(vtu.ugrid.GetNumberOfPoints()), debugLevel) debug.dprint("Elements: " + str(vtu.ugrid.GetNumberOfCells()), debugLevel) debug.dprint("Fields: " + str(len(vtu.GetFieldNames())), debugLevel) for fieldName in vtu.GetFieldNames(): string = fieldName + ", " rank = VtuFieldRank(vtu, fieldName) if rank == 0: string += "scalar" elif rank == 1: string += "vector" elif rank == 2: string += "tensor" else: string += "unknown" string += " field with shape " + str(VtuFieldShape(vtu, fieldName)) debug.dprint(string, debugLevel) debug.dprint("Cell fields: " + str(len(VtuGetCellFieldNames(vtu))), debugLevel) for fieldName in VtuGetCellFieldNames(vtu): string = fieldName debug.dprint(string, debugLevel) return
def GenerateRectangleMesh(xCoords, yCoords, leftId = 1, rightId = 2, topId = 3, bottomId = 4, volumeId = 0, elementFamilyId = elements.ELEMENT_FAMILY_SIMPLEX): """ Generate a structured 2D linear tet rectangular mesh based upon the given x and y coordinates """ debug.dprint("Generating rectangle mesh") nXCoords = len(xCoords) nYCoords = len(yCoords) # Copy and sort the input coords lXCoords = copy.deepcopy(xCoords) lYCoords = copy.deepcopy(yCoords) lXCoords.sort() lYCoords.sort() # Generate map from x, y IDs to node IDs xyToNode = [] index = 0 for i in range(nXCoords): xyToNode.append([index + i for i in range(nYCoords)]) index += nYCoords mesh = meshes.Mesh(2) # Generate node coordinates for x in lXCoords: for y in lYCoords: mesh.AddNodeCoord([x, y]) if elementFamilyId == elements.ELEMENT_FAMILY_SIMPLEX: # Generate volume elements for i in range(nXCoords - 1): debug.dprint("Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint("Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) # Out of a quad, construct 2 triangles # Triangle 1 mesh.AddVolumeElement(elements.Element([xyToNode[i][j], xyToNode[i + 1][j], xyToNode[i + 1][j + 1]], volumeId)) # Triangle 2 mesh.AddVolumeElement(elements.Element([xyToNode[i][j], xyToNode[i + 1][j + 1], xyToNode[i][j + 1]], volumeId)) elif elementFamilyId == elements.ELEMENT_FAMILY_CUBIC: # Generate volume elements for i in range(nXCoords - 1): debug.dprint("Processing x element strip " + str(i + 1) + " of " + str(nXCoords - 1), 2) for j in range(nYCoords - 1): debug.dprint("Processing y element strip " + str(i + 1) + " of " + str(nYCoords - 1), 3) # Quad mesh.AddVolumeElement(elements.Element([xyToNode[i][j], xyToNode[i + 1][j], xyToNode[i][j + 1], xyToNode[i + 1][j + 1]], volumeId)) else: raise Exception("Unsupported element family") # Generate surface elements... # ... for left for i in range(nYCoords - 1): mesh.AddSurfaceElement(elements.Element([xyToNode[0][i], xyToNode[0][i + 1]], leftId)) # ... for right for i in range(nYCoords - 1): mesh.AddSurfaceElement(elements.Element([xyToNode[-1][i], xyToNode[-1][i + 1]], rightId)) # ... for bottom for i in range(nXCoords - 1): mesh.AddSurfaceElement(elements.Element([xyToNode[i][0], xyToNode[i + 1][0]], bottomId)) # ... for top for i in range(nXCoords - 1): mesh.AddSurfaceElement(elements.Element([xyToNode[i][-1], xyToNode[i + 1][-1]], topId)) debug.dprint("Finished generating rectangle mesh") return mesh
import os import sys import tempfile import vtk import fluidity.diagnostics.debug as debug import fluidity.diagnostics.filehandling as filehandling import fluidity.diagnostics.fluiditytools as fluiditytools import fluidity.diagnostics.vtutools as vtktools if not len(sys.argv) == 2: print "Usage: genpvtu basename" sys.exit(1) basename = sys.argv[1] debug.dprint("vtu basename: " + basename) nPieces = fluiditytools.FindMaxVtuId(basename) + 1 debug.dprint("Number of pieces: " + str(nPieces)) # Write to a temporary directory so that the first piece isn't overwritten tempDir = tempfile.mkdtemp() # Create the parallel writer writer = vtk.vtkXMLPUnstructuredGridWriter() writer.SetNumberOfPieces(nPieces) writer.WriteSummaryFileOn() pvtuName = basename + ".pvtu" writer.SetFileName(os.path.join(tempDir, pvtuName)) # Load in the first piece, so that the parallel writer has something to do (and # knows which fields we have)
from __future__ import print_function import os import sys import tempfile import vtk import fluidity.diagnostics.debug as debug import fluidity.diagnostics.filehandling as filehandling import fluidity.diagnostics.fluiditytools as fluiditytools import fluidity.diagnostics.vtutools as vtktools if not len(sys.argv) == 2: print("Usage: genpvtu basename") sys.exit(1) basename = sys.argv[1] debug.dprint("vtu basename: " + basename) nPieces = fluiditytools.FindMaxVtuId(basename) + 1 debug.dprint("Number of pieces: " + str(nPieces)) # Write to a temporary directory so that the first piece isn't overwritten tempDir = tempfile.mkdtemp() # Create the parallel writer writer = vtk.vtkXMLPUnstructuredGridWriter() writer.SetNumberOfPieces(nPieces) writer.WriteSummaryFileOn() pvtuName = basename + ".pvtu" writer.SetFileName(os.path.join(tempDir, pvtuName)) # Load in the first piece, so that the parallel writer has something to do (and # knows which fields we have)
def TimeAveragedVtu(filenames, timeFieldName="Time", baseMesh=None, baseVtu=None): """ Perform a time weighted average of vtus with the supplied filenames. The filenames must be in time order. """ debug.dprint("Computing time averaged vtu") if not baseMesh is None: assert (baseVtu is None) result = baseMesh.ToVtu() elif not baseVtu is None: assert (baseMesh is None) result = CopyVtu(baseVtu) else: result = None if len(filenames) == 0: if result is None: return vtu() else: return result startTime = None finalTime = None lastDt = None nextInputVtu = None for i, filename in enumerate(filenames): debug.dprint("Processing file " + filename) if nextInputVtu is None: inputVtu = vtu(filename) else: inputVtu = nextInputVtu if result is None: result = vtu() # Add the points result.ugrid.SetPoints(inputVtu.ugrid.GetPoints()) # Add the cells result.ugrid.SetCells(inputVtu.ugrid.GetCellTypesArray(), inputVtu.ugrid.GetCellLocationsArray(), inputVtu.ugrid.GetCells()) if len(filenames) == 1: weight = 1.0 else: # Trapezium rule weighting weight = 0.0 if not lastDt is None: weight += lastDt timeField = inputVtu.GetScalarField(timeFieldName) assert (len(timeField) > 0) if startTime is None: startTime = timeField[0] if i < len(filenames) - 1: nextInputVtu = vtu(filenames[i + 1]) nextTimeField = nextInputVtu.GetScalarField(timeFieldName) assert (len(nextTimeField) > 0) if finalTime is None: finalTime = nextTimeField[0] dt = nextTimeField[0] - timeField[0] lastDt = dt weight += dt weight /= 2.0 debug.dprint("weight = " + str(weight)) if i == 0: if not VtuMatchLocations(inputVtu, result): inputVtu = RemappedVtu(inputVtu, result) for fieldName in inputVtu.GetFieldNames(): result.AddField(fieldName, inputVtu.GetField(fieldName) * weight) else: AddtoVtu(result, inputVtu, scale=weight) if len(filenames) > 1: debug.dprint("Start time = " + str(startTime)) debug.dprint("Final time = " + str(finalTime)) DivideVtu(result, finalTime - startTime) debug.dprint("Finished computing time averaged vtu") return result
def EnablePsyco(): if PsycoSupport(): psyco.full() debug.dprint("Enabled psyco specialising compiler") return
def ReadMsh(filename): """ Read a Gmsh msh file """ def ReadNonCommentLine(fileHandle): line = fileHandle.readline() while len(line) > 0: line = line.strip() if len(line) > 0: return line line = fileHandle.readline() return line fileHandle = open(filename, "r") basename = filename.split(".")[0] hasHalo = filehandling.FileExists(basename + ".halo") # Read the MeshFormat section line = ReadNonCommentLine(fileHandle) assert(line == "$MeshFormat") line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) == 3) version = float(lineSplit[0]) fileType = int(lineSplit[1]) dataSize = int(lineSplit[2]) if fileType == 1: # Binary format if dataSize == 4: realFormat = "f" elif dataSize == 8: realFormat = "d" else: raise Exception("Unrecognised real size " + str(dataSize)) iArr = array.array("i") iArr.fromfile(fileHandle, 1) if iArr[0] == 1: swap = False else: iArr.byteswap() if iArr[0] == 1: swap = True else: raise Exception("Invalid one byte") line = ReadNonCommentLine(fileHandle) assert(line == "$EndMeshFormat") # Read the Nodes section line = ReadNonCommentLine(fileHandle) assert(line == "$Nodes") line = ReadNonCommentLine(fileHandle) nNodes = int(line) # Assume dense node IDs, but not necessarily ordered seenNode = [False for i in range(nNodes)] nodeIds = [] nodes = [] lbound = [calc.Inf() for i in range(3)] ubound = [-calc.Inf() for i in range(3)] for i in range(nNodes): iArr = array.array("i") rArr = array.array(realFormat) iArr.fromfile(fileHandle, 1) rArr.fromfile(fileHandle, 3) if swap: iArr.byteswap() rArr.byteswap() nodeId = iArr[0] coord = rArr assert(nodeId > 0) assert(not seenNode[nodeId - 1]) seenNode[nodeId - 1] = True nodeIds.append(nodeId) nodes.append(coord) for j in range(3): lbound[j] = min(lbound[j], coord[j]) ubound[j] = max(ubound[j], coord[j]) line = ReadNonCommentLine(fileHandle) assert(line == "$EndNodes") nodes = utils.KeyedSort(nodeIds, nodes) bound = bounds.BoundingBox(lbound, ubound) indices = bound.UsedDimIndices() dim = len(indices) if dim < 3: nodes = [[coord[index] for index in indices] for coord in nodes] mesh = meshes.Mesh(dim) mesh.AddNodeCoords(nodes) # Read the Elements section line = ReadNonCommentLine(fileHandle) assert(line == "$Elements") line = ReadNonCommentLine(fileHandle) nEles = int(line) i = 0 while i < nEles: iArr = array.array("i") iArr.fromfile(fileHandle, 3) if swap: iArr.byteswap() typeId = iArr[0] nSubEles = iArr[1] nIds = iArr[2] type = GmshElementType(gmshElementTypeId = typeId) for j in range(nSubEles): iArr = array.array("i") iArr.fromfile(fileHandle, 1 + nIds + type.GetNodeCount()) if swap: iArr.byteswap() eleId = iArr[0] assert(eleId > 0) ids = iArr[1:1 + nIds] nodes = FromGmshNodeOrder(utils.OffsetList(iArr[-type.GetNodeCount():], -1), type) element = elements.Element(nodes, ids) if type.GetDim() == dim - 1: mesh.AddSurfaceElement(element) elif type.GetDim() == dim: mesh.AddVolumeElement(element) else: debug.deprint("Warning: Element of type " + str(type) + " encountered in " + str(dim) + " dimensions") i += nSubEles assert(i == nEles) line = ReadNonCommentLine(fileHandle) assert(line == "$EndElements") elif fileType == 0: # ASCII format line = ReadNonCommentLine(fileHandle) assert(line == "$EndMeshFormat") # Read the Nodes section line = ReadNonCommentLine(fileHandle) assert(line == "$Nodes") line = ReadNonCommentLine(fileHandle) nNodes = int(line) # Assume dense node IDs, but not necessarily ordered seenNode = [False for i in range(nNodes)] nodeIds = [] nodes = [] lbound = [calc.Inf() for i in range(3)] ubound = [-calc.Inf() for i in range(3)] for i in range(nNodes): line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) == 4) nodeId = int(lineSplit[0]) coord = [float(comp) for comp in lineSplit[1:]] assert(nodeId > 0) assert(not seenNode[nodeId - 1]) seenNode[nodeId - 1] = True nodeIds.append(nodeId) nodes.append(coord) for j in range(3): lbound[j] = min(lbound[j], coord[j]) ubound[j] = max(ubound[j], coord[j]) line = ReadNonCommentLine(fileHandle) assert(line == "$EndNodes") nodes = utils.KeyedSort(nodeIds, nodes) bound = bounds.BoundingBox(lbound, ubound) indices = bound.UsedDimIndices() dim = len(indices) if dim < 3: nodes = [[coord[index] for index in indices] for coord in nodes] mesh = meshes.Mesh(dim) mesh.AddNodeCoords(nodes) # Read the Elements section line = ReadNonCommentLine(fileHandle) assert(line == "$Elements") line = ReadNonCommentLine(fileHandle) nEles = int(line) for i in range(nEles): line = ReadNonCommentLine(fileHandle) lineSplit = line.split() assert(len(lineSplit) > 3) eleId = int(lineSplit[0]) assert(eleId > 0) typeId = int(lineSplit[1]) nIds = int(lineSplit[2]) type = GmshElementType(gmshElementTypeId = typeId) ids = [int(id) for id in lineSplit[3:3 + nIds]] nodes = FromGmshNodeOrder([int(node) - 1 for node in lineSplit[-type.GetNodeCount():]], type) element = elements.Element(nodes, ids) if type.GetDim() == dim - 1: mesh.AddSurfaceElement(element) elif type.GetDim() == dim: mesh.AddVolumeElement(element) else: debug.deprint("Warning: Element of type " + str(type) + " encountered in " + str(dim) + " dimensions") line = ReadNonCommentLine(fileHandle) assert(line == "$EndElements") # Ignore all remaining sections else: raise Exception("File type " + str(fileType) + " not recognised") fileHandle.close() if hasHalo: # Read the .halo file debug.dprint("Reading .halo file") if mesh_halos.HaloIOSupport(): halos = mesh_halos.ReadHalos(basename + ".halo") mesh.SetHalos(halos) else: debug.deprint("Warning: No .halo I/O support") return mesh
def ReadTriangle(baseName): """ Read triangle files with the given base name, and return it as a mesh """ def StripComment(line): if "#" in line: return line.split("#")[0] else: return line def ReadNonCommentLine(fileHandle): line = fileHandle.readline() while len(line) > 0: line = StripComment(line).strip() if len(line) > 0: return line line = fileHandle.readline() return line # Determine which files exist assert(filehandling.FileExists(baseName + ".node")) hasBound = filehandling.FileExists(baseName + ".bound") hasEdge = filehandling.FileExists(baseName + ".edge") hasFace = filehandling.FileExists(baseName + ".face") hasEle = filehandling.FileExists(baseName + ".ele") hasHalo = filehandling.FileExists(baseName + ".halo") # Read the .node file nodeHandle = open(baseName + ".node", "r") # Extract the meta data line = ReadNonCommentLine(nodeHandle) lineSplit = line.split() assert(len(lineSplit) == 4) nNodes = int(lineSplit[0]) assert(nNodes >= 0) dim = int(lineSplit[1]) assert(dim >= 0) nNodeAttrs = int(lineSplit[2]) assert(nNodeAttrs >= 0) nNodeIds = int(lineSplit[3]) assert(nNodeIds >= 0) mesh = meshes.Mesh(dim) # Read the nodes debug.dprint("Reading .node file") for line in nodeHandle.readlines(): line = StripComment(line) if len(line.strip()) == 0: continue lineSplit = line.split() assert(len(lineSplit) == 1 + dim + nNodeAttrs + nNodeIds) mesh.AddNodeCoord([float(coord) for coord in lineSplit[1:dim + 1]]) assert(mesh.NodeCoordsCount() == nNodes) nodeHandle.close() if hasBound and dim == 1: # Read the .bound file debug.dprint("Reading .bound file") boundHandle = open(baseName + ".bound", "r") # Extract the meta data line = ReadNonCommentLine(boundHandle) lineSplit = line.split() assert(len(lineSplit) == 2) nBounds = int(lineSplit[0]) assert(nBounds >= 0) nBoundIds = int(lineSplit[1]) assert(nBoundIds >= 0) # Read the bounds for line in boundHandle.readlines(): line = StripComment(line) if len(line.strip()) == 0: continue lineSplit = line.split() assert(len(lineSplit) == 2 + nBoundIds) element = elements.Element() for node in lineSplit[1:2]: element.AddNode(int(node) - 1) element.SetIds([int(boundId) for boundId in lineSplit[2:]]) mesh.AddSurfaceElement(element) assert(mesh.SurfaceElementCount() == nBounds) boundHandle.close() if hasEdge and dim == 2: # Read the .edge file debug.dprint("Reading .edge file") edgeHandle = open(baseName + ".edge", "r") # Extract the meta data line = ReadNonCommentLine(edgeHandle) lineSplit = line.split() assert(len(lineSplit) == 2) nEdges = int(lineSplit[0]) assert(nEdges >= 0) nEdgeIds = int(lineSplit[1]) assert(nEdgeIds >= 0) # Read the edges for line in edgeHandle.readlines(): line = StripComment(line) if len(line.strip()) == 0: continue lineSplit = line.split() assert(len(lineSplit) == 3 + nEdgeIds) element = elements.Element() for node in lineSplit[1:3]: element.AddNode(int(node) - 1) element.SetIds([int(edgeId) for edgeId in lineSplit[3:]]) mesh.AddSurfaceElement(element) assert(mesh.SurfaceElementCount() == nEdges) edgeHandle.close() if hasFace and dim > 2: # Read the .face file debug.dprint("Reading .face file") faceHandle = open(baseName + ".face", "r") # Extract the meta data line = ReadNonCommentLine(faceHandle) lineSplit = line.split() assert(len(lineSplit) == 2) nFaces = int(lineSplit[0]) assert(nFaces >= 0) nFaceIds = int(lineSplit[1]) assert(nFaceIds >= 0) # Read the faces for line in faceHandle.readlines(): line = StripComment(line) if len(line.strip()) == 0: continue lineSplit = line.split() assert(len(lineSplit) >= 4 + nFaceIds) element = elements.Element() for node in lineSplit[1:len(lineSplit) - nFaceIds]: element.AddNode(int(node) - 1) element.SetIds([int(faceId) for faceId in lineSplit[len(lineSplit) - nFaceIds:]]) mesh.AddSurfaceElement(element) assert(mesh.SurfaceElementCount() == nFaces) faceHandle.close() if hasEle: # Read the .ele file debug.dprint("Reading .ele file") eleHandle = open(baseName + ".ele", "r") # Extract the meta data line = ReadNonCommentLine(eleHandle) lineSplit = line.split() assert(len(lineSplit) == 3) nEles = int(lineSplit[0]) assert(nEles >= 0) nNodesPerEle = int(lineSplit[1]) assert(nNodesPerEle >= 0) nEleIds = int(lineSplit[2]) assert(nEleIds >= 0) # Read the eles for line in eleHandle.readlines(): line = StripComment(line) if len(line.strip()) == 0: continue lineSplit = line.split() assert(len(lineSplit) == 1 + nNodesPerEle + nEleIds) element = elements.Element() for node in lineSplit[1:len(lineSplit) - nEleIds]: element.AddNode(int(node) - 1) element.SetIds([int(eleId) for eleId in lineSplit[len(lineSplit) - nEleIds:]]) mesh.AddVolumeElement(element) assert(mesh.VolumeElementCount() == nEles) eleHandle.close() if hasHalo: # Read the .halo file debug.dprint("Reading .halo file") if mesh_halos.HaloIOSupport(): halos = mesh_halos.ReadHalos(baseName + ".halo") mesh.SetHalos(halos) else: debug.deprint("Warning: No .halo I/O support") return mesh
def LineVtuCut(inputVtu, origin=(0.0, 0.0, 0.0), direction=(1.0, 0.0, 0.0)): """ Perform a plane-plane double cut to form a 1D line (in 3D space) """ assert (len(origin) == 3) assert (len(direction) == 3) # Copy the input line direction x0 = direction[0] y0 = direction[1] z0 = direction[2] # To form the line from two planar cuts, we need two normal vectors at right # angles to the line direction. # Form the first normal vector by imposing x0 dot x1 = 0, with one component # of x1 equal to one and one equal to zero, where the component in x0 # corresponding to the remaining third component is non-zero if calc.AlmostEquals(z0, 0.0): if calc.AlmostEquals(y0, 0.0): if calc.AlmostEquals(x0, 0.0): raise Exception("Direction has zero length") y1 = 1.0 z1 = 0.0 # x1 = -(y0 y1 + z0 z1) / x0 x1 = -y0 / x0 else: x1 = 1.0 z1 = 0.0 # y1 = -(x0 x1 + z0 z1) / y0 y1 = -x0 / y0 else: x1 = 1.0 y1 = 0.0 # z1 = -(x0 x1 + y0 y1) / z0 z1 = -x0 / z0 # Normalise the first normal vector mag = calc.L2Norm([x1, y1, z1]) x1 /= mag y1 /= mag z1 /= mag # Form the second normal vector via a cross product x2 = y0 * z1 - z0 * y1 y2 = z0 * x1 - x0 * z1 z2 = x0 * y1 - y0 * x1 # Normalise the second normal vector mag = calc.L2Norm([x2, y2, z2]) x2 /= mag y2 /= mag z2 /= mag normal1 = (x1, y1, z1) normal2 = (x2, y2, z2) debug.dprint("Normal 1 = " + str(normal1)) debug.dprint("Normal 2 = " + str(normal2)) # Perform the cuts cutVtu = PlanarVtuCut(inputVtu, origin, normal1) cutVtu = PlanarVtuCut(cutVtu, origin, normal2) return cutVtu