def TetVolume(nodeCoords, signed=False): """ Return the volume of the tetrahedron with the supplied node coordinates """ if optimise.DebuggingEnabled(): type = elements.ElementType(dim=len(nodeCoords[0]), nodeCount=len(nodeCoords)) assert (type.GetElementTypeId() == elements.ELEMENT_TETRAHEDRON) return SimplexVolume(nodeCoords, signed=signed)
def SimplexEdgeVectors(nodeCoords): """ Return the edge vectors for the tetrahedron with the supplied node coordinates """ type = elements.ElementType(dim=len(nodeCoords[0]), nodeCount=len(nodeCoords)) assert (type.GetElementFamilyId() == elements.ELEMENT_FAMILY_SIMPLEX) return [[nodeCoord[i] - nodeCoords[0][i] for i in range(type.GetDim())] for nodeCoord in nodeCoords[1:]]
def SimplexIntegral(nodeCoords, nodeCoordVals): """ Integrate a P1 field over a simplex """ type = elements.ElementType(dim=len(nodeCoords[0]), nodeCount=len(nodeCoords)) assert (type.GetElementFamilyId() == elements.ELEMENT_FAMILY_SIMPLEX) assert (len(nodeCoordVals) == type.GetNodeCount()) integral = nodeCoordVals[0] for val in nodeCoordVals[1:]: integral += val integral *= SimplexVolume(nodeCoords) / float(type.GetNodeCount()) return integral
def SimplexVolume(nodeCoords, signed=False): """ Return the volume of the simplex with the supplied node coordinates """ type = elements.ElementType(dim=len(nodeCoords[0]), nodeCount=len(nodeCoords)) assert (type.GetElementFamilyId() == elements.ELEMENT_FAMILY_SIMPLEX) volume = calc.Determinant(SimplexEdgeVectors(nodeCoords)) / calc.Factorial( type.GetDim()) if signed: return volume else: return abs(volume)
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 ReadGid(filename): """ Read a GiD file with the given filename, and return it as a mesh """ debug.dprint("Reading GiD mesh with filename " + filename) fileHandle = open(filename, "r") # Read the header header = fileHandle.readline() lineSplit = header.split() assert(lineSplit[0] == "MESH") dimension = None elemType = None nnode = None for i, word in enumerate(lineSplit[:len(lineSplit) - 1]): if word == "dimension": dimension = int(lineSplit[i + 1]) assert(dimension >= 0) elif word == "ElemType": elemType = lineSplit[i + 1] elif word == "Nnode": nnode = int(lineSplit[i + 1]) assert(nnode >= 0) assert(not dimension is None) assert(not elemType is None) assert(not nnode is None) debug.dprint("Dimension = " + str(dimension)) debug.dprint("Element type = " + elemType) debug.dprint("Element nodes = " + str(nnode)) # Read the nodes nodeCoords = [] line = fileHandle.readline() index = 0 while len(line) > 0: if line.strip() == "Coordinates": line = fileHandle.readline() while not line.strip() == "end coordinates": assert(len(line) > 0) index += 1 lineSplit = line.split() assert(len(lineSplit) == 1 + dimension) assert(int(lineSplit[0]) == index) nodeCoords.append([float(coord) for coord in lineSplit[1:]]) line = fileHandle.readline() break line = fileHandle.readline() debug.dprint("Nodes: " + str(index)) # Check for unused dimensions lbound = [calc.Inf() for i in range(dimension)] ubound = [-calc.Inf() for i in range(dimension)] for nodeCoord in nodeCoords: for i, val in enumerate(nodeCoord): lbound[i] = min(lbound[i], val) ubound[i] = max(ubound[i], val) boundingBox = bounds.BoundingBox(lbound, ubound) actualDimension = boundingBox.UsedDim() if not dimension == actualDimension: debug.deprint("Dimension suggested by bounds = " + str(actualDimension)) debug.deprint("Warning: Header dimension inconsistent with bounds") dimension = actualDimension coordMask = boundingBox.UsedDimCoordMask() nodeCoords = [utils.MaskList(nodeCoord, coordMask) for nodeCoord in nodeCoords] mesh = meshes.Mesh(dimension) mesh.AddNodeCoords(nodeCoords) fileHandle.seek(0) # Read the volume elements line = fileHandle.readline() index = 0 while len(line) > 0: if line.strip() == "Elements": line = fileHandle.readline() while not line.strip() == "end elements": assert(len(line) > 0) index += 1 lineSplit = line.split() assert(len(lineSplit) == 1 + nnode) assert(int(lineSplit[0]) == index) # Note: GiD file indexes nodes from 1, Mesh s index nodes from 0 mesh.AddVolumeElement(elements.Element(nodes = FromGidNodeOrder([int(node) - 1 for node in lineSplit[1:]], elements.ElementType(dim = dimension, nodeCount = nnode)))) line = fileHandle.readline() break line = fileHandle.readline() debug.dprint("Elements: " + str(index)) fileHandle.close() debug.dprint("Finished reading GiD mesh") return mesh