예제 #1
0
    def connections(self):
        p = self.model.pardim

        # For every object in the model...
        for node in self.nodes:

            # Loop over its sections of one lower parametric dimension
            # That is, for faces, loop over edges, and for volumes, loop over faces
            for node_sub_idx, sub in enumerate(node.lower_nodes[p - 1]):
                # The sub-node should have at most one neighbour, excluding the original node
                neighbours = set(sub.higher_nodes[p]) - {node}
                assert len(neighbours) <= 1
                if not neighbours:
                    continue

                # Get the neighbour node and its section index to the same sub-node
                neigh = next(iter(neighbours))
                neigh_sub_idx = neigh.lower_nodes[p - 1].index(sub)

                # Only output if the node has a lower ID than the neighbour,
                # otherwise we'll get this pair when the reverse pair is found
                if self.node_ids[node] > self.node_ids[neigh]:
                    continue

                # Find the actual SplineObjects representing the
                # sub-node, as it is viewed from the perspective of
                # both the node and the neighbour, then compute the
                # orientation mapping between them
                node_sec_idx = section_from_index(p, p - 1, node_sub_idx)
                node_sub = node.obj.section(*node_sec_idx)
                neigh_sec_idx = section_from_index(p, p - 1, neigh_sub_idx)
                neigh_sub = neigh.obj.section(*neigh_sec_idx)

                # print('------')
                # print(node.obj)
                # print(neigh.obj, self.node_ids[neigh] + 1)
                orientation = Orientation.compute(node_sub, neigh_sub)
                # print(orientation.flip, orientation.perm, orientation.ifem_format)

                yield IFEMConnection(
                    master=self.node_ids[node] + 1,
                    slave=self.node_ids[neigh] + 1,
                    midx=node_sub_idx + 1,
                    sidx=neigh_sub_idx + 1,
                    orient=orientation.ifem_format,
                )
예제 #2
0
 def face(self, i):
     """Return the i'th face."""
     return self.section(*section_from_index(self.pardim, 2, i))
예제 #3
0
 def edge(self, i):
     """Return the i'th edge."""
     return self.section(*section_from_index(self.pardim, 1, i))
예제 #4
0
 def corner(self, i):
     """Return the i'th corner."""
     return self.section(*section_from_index(self.pardim, 0, i))
예제 #5
0
    def faces(self):
        """Return all faces owned by this node, as a list of numpy arrays with dtype `face_t`."""
        assert self.pardim == 3
        assert self.obj.order() == (2, 2, 2)
        shape = [len(kvec) - 1 for kvec in self.obj.knots()]
        ncells = np.prod(shape)
        retval = []

        def mkindex(dim, z, a, b):
            rval = [a, b] if dim != 1 else [b, a]
            rval.insert(dim, z)
            return tuple(rval)

        lower = iter(self.lower_nodes[-1])
        for d in range(self.pardim):
            # Number of faces in one "slice"
            nperslice = ncells // shape[d]

            # First, get all internal faces in this direction
            # The owner (lowest cell index) is guaranteed to be toward the lower end
            # TODO: We assume a right-hand coordinate system here
            nfaces = ncells - nperslice
            faces = np.empty((nfaces, ), dtype=face_t)
            faces['nodes'][:, 0] = self.cp_numbers[mkindex(
                d, np.s_[1:-1], np.s_[:-1], np.s_[:-1])].flatten()
            faces['nodes'][:, 1] = self.cp_numbers[mkindex(
                d, np.s_[1:-1], np.s_[1:], np.s_[:-1])].flatten()
            faces['nodes'][:, 2] = self.cp_numbers[mkindex(
                d, np.s_[1:-1], np.s_[1:], np.s_[1:])].flatten()
            faces['nodes'][:, 3] = self.cp_numbers[mkindex(
                d, np.s_[1:-1], np.s_[:-1], np.s_[1:])].flatten()
            faces['owner'] = self.cell_numbers[mkindex(d, np.s_[:-1], np.s_[:],
                                                       np.s_[:])].flatten()
            faces['neighbor'] = self.cell_numbers[mkindex(
                d, np.s_[1:], np.s_[:], np.s_[:])].flatten()
            retval.append(faces)

            # Go through the two boundaries
            for bdnode, bdindex in zip(islice(lower, 2), (0, -1)):
                assert bdnode.nhigher in {1, 2}

                # Faces on an interface are only returned from the owner
                if bdnode.owner is not self:
                    continue

                faces = np.empty((nperslice, ), dtype=face_t)
                faces['nodes'][:, 0] = self.cp_numbers[mkindex(
                    d, bdindex, np.s_[:-1], np.s_[:-1])].flatten()
                faces['nodes'][:, 1] = self.cp_numbers[mkindex(
                    d, bdindex, np.s_[1:], np.s_[:-1])].flatten()
                faces['nodes'][:, 2] = self.cp_numbers[mkindex(
                    d, bdindex, np.s_[1:], np.s_[1:])].flatten()
                faces['nodes'][:, 3] = self.cp_numbers[mkindex(
                    d, bdindex, np.s_[:-1], np.s_[1:])].flatten()
                faces['owner'] = self.cell_numbers[mkindex(
                    d, bdindex, np.s_[:], np.s_[:])].flatten()
                faces['name'] = bdnode.name

                # If we're on the left boundary, the face normal must point in the other direction
                # NOTE: We copy when swapping here, since we are swapping values which are views into
                # a mutable array!
                if bdindex == 0:
                    faces['nodes'][:, 1], faces['nodes'][:, 3] = (
                        faces['nodes'][:, 3].copy(), faces['nodes'][:,
                                                                    1].copy())

                # If there's a neighbor on the interface we need neighbouring cell numbers
                if bdnode.nhigher == 1:
                    faces['neighbor'] = -1
                else:
                    neighbor = next(c for c in bdnode.higher_nodes[3]
                                    if c is not self)

                    # Find out which face the interface is as numbered from the neighbor's perspective
                    nb_index = neighbor.lower_nodes[2].index(bdnode)

                    # Get the spline object on that interface as oriented from the neighbor's perspective
                    nb_sec = section_from_index(3, 2, nb_index)
                    nb_obj = neighbor.obj.section(*nb_sec)

                    # Compute the relative orientation
                    ori = Orientation.compute(bdnode.obj, nb_obj)

                    # Get the neighbor cell numbers from the neighbor's perspective, and map them to our system
                    cellidxs = neighbor.cell_numbers[_section_to_index(nb_sec)]
                    faces['neighbor'] = ori.map_array(cellidxs).flatten()

                retval.append(faces)

        for faces in retval:
            assert ((faces['owner'] < faces['neighbor']) |
                    (faces['neighbor'] == -1)).all()
        return retval