示例#1
0
    def Map(self, coord):
        if optimise.DebuggingEnabled():
            assert (len(coord) == 3)
            assert (coord[2] <= self._maxZ)
            assert (coord[2] >= self._minZ)

        distanceFromBottom = coord[2] - self._minZ
        r = calc.L2Norm(coord[:2])
        if optimise.DebuggingEnabled():
            assert (r >= self._a and r <= self._b)
        distanceFromInnerWall = r - self._a
        distanceFromOuterWall = self._b - r

        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]
示例#2
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
示例#3
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)
示例#4
0
    def Map(self, coord):
        if optimise.DebuggingEnabled():
            assert (len(coord) == 3)
            assert (coord[2] <= self._maxZ)
            assert (coord[2] >= self._minZ)

        r = calc.L2Norm(coord[:2])
        phi = math.atan2(coord[1], coord[0])

        phi += self._phi * ((coord[2] - self._minZ) /
                            (self._maxZ - self._minZ))

        newX = r * math.cos(phi)
        newY = r * math.sin(phi)

        return [newX, newY, coord[2]]
示例#5
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
示例#6
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
示例#7
0
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