Ejemplo n.º 1
0
    def Map(self, coord):
        if optimise.DebuggingEnabled():
            assert (len(coord) == 3)
            assert (coord[0] >= self._a and coord[0] <= self._b)
            assert (coord[2] <= self._maxZ)
            assert (coord[2] >= self._minZ)

        distanceFromBottom = coord[2] - self._minZ
        distanceFromInnerWall = coord[0] - self._a
        distanceFromOuterWall = self._b - coord[0]

        if calc.AlmostEquals(self._phiTop, 0.0):
            localMaxZ = self._maxZ
        elif self._phiTop > 0.0:
            localMaxZ = self._maxZ - distanceFromOuterWall * math.tan(
                self._phiTop)
        else:
            localMaxZ = self._maxZ + distanceFromInnerWall * math.tan(
                self._phiTop)
        if calc.AlmostEquals(self._phiBottom, 0.0):
            localMinZ = self._minZ
        elif self._phiBottom > 0.0:
            localMinZ = self._minZ + distanceFromInnerWall * math.tan(
                self._phiBottom)
        else:
            localMinZ = self._minZ - distanceFromOuterWall * math.tan(
                self._phiBottom)
        newZ = localMinZ + (distanceFromBottom /
                            (self._maxZ - self._minZ)) * (localMaxZ -
                                                          localMinZ)

        return [coord[0], coord[1], newZ]
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    def UsedDimCoordMask(self):
        """
    Return a mask, masking dimensions unused in the bounding box
    """

        return [
            not calc.AlmostEquals(
                self._lbound[i], self._ubound[i], tolerance=self._dimTolerance)
            for i in range(self.Dim())
        ]
Ejemplo n.º 4
0
    def ToVtu(self, axis=(0.0, 1.0, 0.0), quadMesh=False):
        assert (not self._shape is None)

        vtu = self.Mesh(quadMesh=quadMesh).ToVtu()

        name = self.GetName()
        if name is None:
            name = "UnknownField"

        data = []
        for i in range(self.YCoordsCount()):
            for j in range(self.XCoordsCount()):
                data.append(self.GetVal(j, i))
        data = numpy.array(data)
        data.shape = (self.XCoordsCount() * self.YCoordsCount(),
                      self._DataLen())
        vtu.AddField(name, data)

        if not calc.AlmostEquals(axis[0], 0.0) or not calc.AlmostEquals(
                axis[1], 1.0) or not calc.AlmostEquals(axis[2], 0.0):
            transform = vtk.vtkTransform()
            transform.Identity()
            # Find the rotation axis
            # (0, 1, 0) x axis
            rotationAxis = [-axis[2], 0.0, -axis[0]]
            # Normalise
            rotationAxisMagnitude = calc.L2Norm(rotationAxis)
            rotationAxis = [
                val / rotationAxisMagnitude for val in rotationAxis
            ]
            # Find the rotation angle
            angle = calc.Rad2Deg(math.acos(axis[1] / calc.L2Norm(axis)))
            # Rotation
            transform.RotateWXYZ(angle, rotationAxis[0], rotationAxis[1],
                                 rotationAxis[2])
            transform.Update()
            newPoints = vtk.vtkPoints()
            transform.TransformPoints(vtu.ugrid.GetPoints(), newPoints)
            vtu.ugrid.SetPoints(newPoints)

        return vtu
Ejemplo n.º 5
0
    def UsedDim(self):
        """
    Return the dimensions actually used in the bounding box
    """

        dim = 0
        for i in range(len(self._lbound)):
            if not calc.AlmostEquals(self._lbound[i],
                                     self._ubound[i],
                                     tolerance=self._dimTolerance):
                dim += 1

        return dim
Ejemplo n.º 6
0
def CylinderVtuCut(inputVtu,
                   radius,
                   origin=(0.0, 0.0, 0.0),
                   axis=(0.0, 0.0, 1.0)):
    """
  Perform a 3D cylinder cut of a vtu
  """

    assert (len(origin) == 3)
    assert (len(axis) == 3)

    # An implicit function with which to cut
    cylinder = vtk.vtkCylinder()
    cylinder.SetRadius(radius)
    cylinder.SetCenter((0.0, 0.0, 0.0))
    # Generate the transform
    transform = vtk.vtkTransform()
    transform.Identity()
    if not calc.AlmostEquals(axis[0], 0.0) or not calc.AlmostEquals(
            axis[1], 1.0) or not calc.AlmostEquals(axis[2], 0.0):
        # Find the rotation axis
        # (0, 1, 0) x axis
        rotationAxis = [-axis[2], 0.0, -axis[0]]
        # Normalise
        rotationAxisMagnitude = calc.L2Norm(rotationAxis)
        rotationAxis = [val / rotationAxisMagnitude for val in rotationAxis]
        # Find the rotation angle
        angle = calc.Rad2Deg(math.acos(axis[1] / calc.L2Norm(axis)))
        # Rotation
        transform.RotateWXYZ(angle, rotationAxis[0], rotationAxis[1],
                             rotationAxis[2])
    # Translation
    transform.Translate(origin[0], origin[1], origin[2])
    # Set the transform
    cylinder.SetTransform(transform)

    return ImplicitFunctionVtuCut(inputVtu, cylinder)
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
def JoinStat(*args):
    """
  Joins a series of stat files together. Useful for combining checkpoint .stat
  files. Selects data in later stat files over earlier stat files. Assumes
  data in stat files are sorted by ElapsedTime.
  """

    nStat = len(args)
    assert (nStat > 0)
    times = [stat["ElapsedTime"] for stat in args]

    startT = [t[0] for t in times]
    permutation = utils.KeyedSort(startT, range(nStat))
    stats = [args[index] for index in permutation]
    startT = [startT[index] for index in permutation]
    times = [times[index] for index in permutation]

    endIndices = numpy.array([len(time) for time in times], dtype=int)
    for i, t in enumerate(times[:-1]):
        for j, time in enumerate(t):
            if calc.AlmostEquals(startT[i + 1], time, tolerance=1.0e-6):
                endIndices[i] = max(j - 1, 0)
                break
            elif startT[i + 1] < time:
                endIndices[i] = j
                break
    debug.dprint("Time ranges:")
    if len(times) > 0:
        for i in range(nStat):
            debug.dprint((startT[i], times[i][endIndices[i] - 1]))
    else:
        debug.dprint("No data")

    dataIndices = numpy.empty(len(args) + 1, dtype=int)
    dataIndices[0] = 0
    for i, index in enumerate(endIndices):
        dataIndices[i + 1] = dataIndices[i] + index

    stat = stats[0]
    data = {}
    for key in stat.keys():
        arr = stat[key]
        shape = list(arr.shape)
        shape[0] = dataIndices[-1]
        data[key] = numpy.empty(shape, dtype=arr.dtype)
        data[key][:dataIndices[1]] = arr[:endIndices[0]]
        data[key][dataIndices[1]:] = calc.Nan()
    delimiter = stat.GetDelimiter()

    for i in range(1, nStat):
        stat = stats[i]
        for key in stat.keys():
            arr = stat[key]
            if not key in data:
                shape = list(arr.shape)
                shape[0] = dataIndices[-1]
                data[key] = numpy.empty(shape, dtype=arr.dtype)
                data[key][:dataIndices[i]] = calc.Nan()
                data[key][dataIndices[i + 1]:] = calc.Nan()
            data[key][dataIndices[i]:dataIndices[i + 1]] = arr[:endIndices[i]]

    output = Stat(delimiter=delimiter)
    for key in data.keys():
        output[key] = numpy.array(data[key])

    return output
Ejemplo n.º 10
0
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