def _build_eval_matrix(V, points): """Build the sparse m-by-n matrix that maps a coefficient set for a function in V to the values of that function at m given points.""" # See <https://www.allanswered.com/post/lkbkm/#zxqgk> mesh = V.mesh() bbt = BoundingBoxTree() bbt.build(mesh) dofmap = V.dofmap() el = V.element() sdim = el.space_dimension() rows = [] cols = [] data = [] for i, x in enumerate(points): cell_id = bbt.compute_first_entity_collision(Point(*x)) cell = Cell(mesh, cell_id) coordinate_dofs = cell.get_vertex_coordinates() rows.append(np.full(sdim, i)) cols.append(dofmap.cell_dofs(cell_id)) v = el.evaluate_basis_all(x, coordinate_dofs, cell_id) data.append(v) rows = np.concatenate(rows) cols = np.concatenate(cols) data = np.concatenate(data) m = len(points) n = V.dim() matrix = sparse.csr_matrix((data, (rows, cols)), shape=(m, n)) return matrix
def mesh_fixup(mesh): """Refine cells which have all vertices on boundary and return a new mesh.""" cf = CellFunction('bool', mesh) tdim = mesh.topology().dim() mesh.init(tdim-1, tdim) for f in facets(mesh): # Boundary facet? # TODO: Here we could check supplied facet function or subdomain if not f.exterior(): continue # Pick adjacent cell c = Cell(mesh, f.entities(tdim)[0]) # Number of vertices on boundary num_bad_vertices = sum(1 for v in vertices(c) if any(fv.exterior() for fv in facets(v))) assert num_bad_vertices <= c.num_vertices() # Refine cell if all vertices are on boundary if num_bad_vertices == c.num_vertices(): cf[c] = True return refine(mesh, cf)
def write_fenics_file(ofile, mesh, editor): dim = mesh.geometry().dim() for i in range(1, len(cell_map) + 1): if dim == 2: editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1, cell_map[i][2] - 1) else: editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1, cell_map[i][2] - 1, cell_map[i][3] - 1) mesh.order() # Set MeshValueCollections from info in boundary_cell #mvc = mesh.domains().markers(dim-1) md = mesh.domains() for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell - 1) vertices_of_cell = dolfin_cell.entities(0) vertices_of_face = nds - 1 for jj, ff in enumerate(facets(dolfin_cell)): facet_vertices = ff.entities(0) if all(map(lambda x: x in vertices_of_face, facet_vertices)): local_index = jj break #mvc.set_value(cell-1, local_index, zone) md.set_marker((ff.index(), zone), dim - 1) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def write_fenics_file(ofile, mesh, editor): dim = mesh.geometry().dim() for i in range(1, len(cell_map)+1): if dim == 2: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1) else: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1, cell_map[i][3]-1) mesh.order() # Set MeshValueCollections from info in boundary_cell #mvc = mesh.domains().markers(dim-1) md = mesh.domains() for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell-1) vertices_of_cell = dolfin_cell.entities(0) vertices_of_face = nds - 1 for jj, ff in enumerate(facets(dolfin_cell)): facet_vertices = ff.entities(0) if all(map(lambda x: x in vertices_of_face, facet_vertices)): local_index = jj break #mvc.set_value(cell-1, local_index, zone) md.set_marker((ff.index(), zone), dim-1) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def test_distance_interval(): mesh = UnitIntervalMesh(MPI.comm_self, 1) cell = Cell(mesh, 0) assert round(cell.distance(Point(-1.0)) - 1.0, 7) == 0 assert round(cell.distance(Point(0.5)) - 0.0, 7) == 0
def test_multi_ps_vector(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a vector for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(c_ids) * 10.0) == 0
def test_multi_ps_vector(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a vector for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0)*v*dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(c_ids)*10.0) == 0
def test_multi_ps_matrix(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a matrix for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) A = assemble(Constant(0.0)*dot(u, v)*dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks b sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2*len(c_ids)*10) == 0
def test_distance_interval(): mesh = UnitIntervalMesh(MPI.comm_self, 1) cell = Cell(mesh, 0) assert round(cell.distance(numpy.array([-1.0, 0, 0])) - 1.0, 7) == 0 assert round(cell.distance(numpy.array([0.5, 0, 0])) - 0.0, 7) == 0
def test_multi_ps_matrix(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a matrix for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) A = assemble(Constant(0.0) * dot(u, v) * dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks b sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2 * len(c_ids) * 10) == 0
def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() shape = V.ufl_element().value_shape() degree = V.ufl_element().degree() # A fake instanc to talk to with the world adapter = type( 'MiroHack', (Expression, ), { 'value_shape': lambda self_, : shape, 'eval': lambda self_, values, x: self.eval(values, x) }) self.__adapter = adapter(degree=degree) is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry( ).dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size())
def test_distance_triangle(): mesh = UnitSquareMesh(MPI.comm_self, 1, 1) cell = Cell(mesh, 1) assert round(cell.distance(Point(-1.0, -1.0)) - numpy.sqrt(2), 7) == 0 assert round(cell.distance(Point(-1.0, 0.5)) - 1, 7) == 0 assert round(cell.distance(Point(0.5, 0.5)) - 0.0, 7) == 0
def test_distance_tetrahedron(): mesh = UnitCubeMesh(MPI.comm_self, 1, 1, 1) cell = Cell(mesh, 5) assert round(cell.distance(Point(-1.0, -1.0, -1.0)) - numpy.sqrt(3), 7) == 0 assert round(cell.distance(Point(-1.0, 0.5, 0.5)) - 1, 7) == 0 assert round(cell.distance(Point(0.5, 0.5, 0.5)) - 0.0, 7) == 0
def __init__(self, u, locations, t0=0.0, record=''): # The idea here is that u(x) means: search for cell containing x, # evaluate the basis functions of that element at x, restrict # the coef vector of u to the cell. Of these 3 steps the first # two don't change. So we cache them # Check the scalar assumption assert u.value_rank() == 0 and u.value_size() == 1 # Locate each point mesh = u.function_space().mesh() limit = mesh.num_entities_global(mesh.topology().dim()) bbox_tree = mesh.bounding_box_tree() cells_for_x = [None] * len(locations) for i, x in enumerate(locations): cell = bbox_tree.compute_first_entity_collision(Point(*x)) if -1 < cell < limit: cells_for_x[i] = cell # Ignore the cells that are not in the mesh. Note that we don't # care if a node is found in several cells -l think CPU interface xs_cells = filter(lambda (xi, c): c is not None, zip(locations, cells_for_x)) V = u.function_space() element = V.dolfin_element() coefficients = np.zeros(element.space_dimension()) # I build a series of functions bound to right variables that # when called compute the value at x evals = [] locations = [] for x, ci in xs_cells: basis_matrix = np.zeros(element.space_dimension()) cell = Cell(mesh, ci) vertex_coords, orientation = cell.get_vertex_coordinates( ), cell.orientation() # Eval the basis once element.evaluate_basis_all(basis_matrix, x, vertex_coords, orientation) def foo(A=basis_matrix, cell=cell, vc=vertex_coords): # Restrict for each call using the bound cell, vc ... u.restrict(coefficients, element, cell, vc, cell) # A here is bound to the right basis_matri return np.dot(A, coefficients) evals.append(foo) locations.append(x) self.probes = evals self.locations = locations self.rank = MPI.rank(mesh.mpi_comm()) self.data = [] self.record = record # Make the initial record self.probe(t=t0)
def test_volume_quadrilateralR3(coordinates): mesh = Mesh(MPI.comm_world, CellType.Type.quadrilateral, numpy.array(coordinates, dtype=numpy.float64), numpy.array([[0, 1, 2, 3]], dtype=numpy.int32), [], cpp.mesh.GhostMode.none) mesh.init() cell = Cell(mesh, 0) assert cell.volume() == 1.0
def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0
def __init__(self, V, **kwargs): super().__init__(self, element=V.ufl_element(), **kwargs) self.elm = V.element() self.mesh = V.mesh() is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size())
def test_save_and_read_mesh_value_collection(tempdir): ndiv = 2 filename = os.path.join(tempdir, "mesh_value_collection.h5") mesh = UnitCubeMesh(MPI.comm_world, ndiv, ndiv, ndiv) def point2list(p): return [p[0], p[1], p[2]] # write to file with HDF5File(mesh.mpi_comm(), filename, 'w') as f: for dim in range(mesh.topology.dim): mvc = MeshValueCollection("size_t", mesh, dim) mesh.create_entities(dim) for e in MeshEntities(mesh, dim): # this can be easily computed to the check the value val = int(ndiv * sum(point2list(e.midpoint()))) + 1 mvc.set_value(e.index(), val) f.write(mvc, "/mesh_value_collection_{}".format(dim)) # read from file with HDF5File(mesh.mpi_comm(), filename, 'r') as f: for dim in range(mesh.topology.dim): mvc = f.read_mvc_size_t(mesh, "/mesh_value_collection_{}".format(dim)) # check the values for (cell, lidx), val in mvc.values().items(): eidx = Cell(mesh, cell).entities(dim)[lidx] mid = point2list(MeshEntity(mesh, dim, eidx).midpoint()) assert val == int(ndiv * sum(mid)) + 1
def convert_vector_nodes_to_cells(root_dir, mesh, V): # Extract constants total_cell_num = mesh.num_cells() dofs_num_per_cell = len(V.dofmap().cell_dofs(0)) # Pre-define empty arrays dof_index_to_cell_table = np.empty((total_cell_num, dofs_num_per_cell), dtype=np.uint32) cell_volumes = np.empty(total_cell_num) cell_coordinates = np.empty((total_cell_num, 3)) # Generate cell-to-dof-indices & cell-to-volume matching table & cell coordinates file_path1 = root_dir + 'dof_index_to_cell_table.npy' file_path2 = root_dir + 'cell_volumes.npy' file_path3 = root_dir + 'cell_coordinates.npy' if (os.path.isfile(file_path1)) & (os.path.isfile(file_path2)) & (os.path.isfile(file_path3)): dof_index_to_cell_table = np.load(file_path1) cell_volumes = np.load(file_path2) cell_coordinates = np.load(file_path3) else: print("No cell information file detected") print(" ==> Creating new cell information") for cell_num in range(total_cell_num): dof_index_to_cell_table[cell_num] = V.dofmap().cell_dofs(cell_num) cell_volumes[cell_num] = Cell(mesh, cell_num).volume() cell_coordinates[cell_num] = MeshEntity(mesh, 3, cell_num).midpoint().array() np.save(file_path1, dof_index_to_cell_table) np.save(file_path2, cell_volumes) np.save(file_path3, cell_coordinates) return (cell_volumes, cell_coordinates, dof_index_to_cell_table)
def find_low(mesh, V, Ause): V2dm = V.dofmap() cq2 = MeshQuality.radius_ratios(mesh) cq = cq2.array() indices = np.where(cq < 0.1)[0] dof_set = [] cell_set = [] for i in indices: cell = Cell(mesh, i) for v in vertices(cell): for c in cells(v): cell_set += [c.index()] dof_set.extend(V2dm.cell_dofs(c.index())) bad_set = list(set(dof_set)) bad_cells = list(set(cell_set)) # print('BAD CELLS=', bad_cells) # print(len(bad_cells)) # print('BAD DOFS=', bad_dofs) # print(len(bad_dofs)) # check redundancy re_dofs = [] for d1 in bad_set: for d2 in bad_set: if Ause[d1, d2] != 0: re_dofs.append(d2) bad_dofs = list(set(re_dofs)) return bad_dofs
def ExtractPoints(structure): if isinstance(structure, df.Mesh): mesh = structure dim = mesh.num_cells() dofmap = None elif isinstance(structure, df.FunctionSpace): ufl = structure.ufl_element() if ufl.degree() != 0 or ufl.family() != 'Discontinuous Lagrange': raise ValueError mesh = structure.mesh() dim = structure.dim() dofmap = structure.dofmap() else: raise ValueError Cells = [Cell(mesh, i) for i in range(mesh.num_cells())] topological_dim = mesh.geometry().dim() X = np.zeros((dim, topological_dim)) for cell in Cells: if dofmap is not None: index = dofmap.cell_dofs(cell.index()) else: index = cell.index() X[index, :] = cell.midpoint().array()[0:topological_dim] return X
def _get_changes(self, cell_index): 'Get identifiers for positions and labels that were changed in cell.' changed_positions = [] changed_labels = [] order = self.order first_dof = self.first_dof for i, j in enumerate(self.component): cell = Cell(self.mesh, cell_index) dofs = self.dofmaps[j].cell_dofs(cell_index) dofs_x = self.dofmaps[j].tabulate_coordinates(cell) for dof, dof_x in zip(dofs, dofs_x): dof_x_str = x_to_str(dof_x) # Append to change if dof position was not plotted yet if not (dof_x_str in self.positions): self.positions[dof_x_str] = dof_x.tolist() changed_positions.append(dof_x_str) dof = dof if order == 'global' else dof - first_dof # If dof label was no created yet create structure for label if not (dof_x_str in self.labels): self.labels[dof_x_str] =\ [[] for k in range(len(self.dofmaps))] self.labels[dof_x_str][i].append(dof) changed_labels.append(dof_x_str) else: # We have dofmaps that have dofs in shared position # Structure created so just append if not (dof in self.labels[dof_x_str][i]): self.labels[dof_x_str][i].append(dof) changed_labels.append(dof_x_str) # Make unique changed_labels = set(changed_labels) return changed_positions, changed_labels
def test_local_assembler_1D(): mesh = UnitIntervalMesh(MPI.comm_world, 20) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) c = Cell(mesh, 0) a_scalar = 1.0 * dx(domain=mesh) a_vector = v * dx a_matrix = u * v * dx A_scalar = assemble_local(a_scalar, c) A_vector = assemble_local(a_vector, c) A_matrix = assemble_local(a_matrix, c) assert isinstance(A_scalar, float) assert numpy.isclose(A_scalar, 0.05) assert isinstance(A_vector, numpy.ndarray) assert A_vector.shape == (2,) assert numpy.isclose(A_vector[0], 0.025) assert numpy.isclose(A_vector[1], 0.025) assert isinstance(A_matrix, numpy.ndarray) assert A_matrix.shape == (2, 2) assert numpy.isclose(A_matrix[0, 0], 1 / 60) assert numpy.isclose(A_matrix[0, 1], 1 / 120) assert numpy.isclose(A_matrix[1, 0], 1 / 120) assert numpy.isclose(A_matrix[1, 1], 1 / 60)
class FEBasisFunction(object): '''Evaluator of dof of V on functions''' def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() shape = V.ufl_element().value_shape() degree = V.ufl_element().degree() # A fake instanc to talk to with the world adapter = type('MiroHack', (Expression, ), {'value_shape': lambda self_, : shape, 'eval': lambda self_, values, x: self.eval(values, x)}) self.__adapter = adapter(degree=degree) is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size()) @property def dof(self): return self.__dof @dof.setter def dof(self, value): assert value < self.elm.space_dimension() self.__dof = value @property def cell(self): return self.__cell @cell.setter def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_ def eval(self, values, x): self.elm.evaluate_basis(self.dof, values[:], x, self.__cell_vertex_x, self.__cell_orientation) def __call__(self, x): self.eval(self.__values, x) return 1*self.__values def as_expression(self): return self.__adapter
class FEBasisFunction(object): '''Evaluator of dof of V on functions''' def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() shape = V.ufl_element().value_shape() degree = V.ufl_element().degree() # A fake instanc to talk to with the world adapter = type( 'MiroHack', (Expression, ), { 'value_shape': lambda self_, : shape, 'eval': lambda self_, values, x: self.eval(values, x) }) self.__adapter = adapter(degree=degree) is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry( ).dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size()) @property def dof(self): return self.__dof @dof.setter def dof(self, value): assert value < self.elm.space_dimension() self.__dof = value @property def cell(self): return self.__cell @cell.setter def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_ def eval(self, values, x): self.elm.evaluate_basis(self.dof, values[:], x, self.__cell_vertex_x, self.__cell_orientation) def __call__(self, x): self.eval(self.__values, x) return 1 * self.__values def as_expression(self): return self.__adapter
def test_volume_quadrilateral_coplanarity_check_2(scaling): with pytest.raises(RuntimeError) as error: # Unit square cell scaled down by 'scaling' and the first # vertex is distorted so that the vertices are clearly non # coplanar mesh = Mesh( MPI.comm_world, CellType.Type.quadrilateral, numpy.array([[1.0, 0.5, 0.6], [0.0, scaling, 0.0], [0.0, 0.0, scaling], [0.0, 1.0, 1.0]], dtype=numpy.float64), numpy.array([[0, 1, 2, 3]], dtype=numpy.int32), [], cpp.mesh.GhostMode.none) mesh.init() cell = Cell(mesh, 0) cell.volume() assert "are not coplanar" in str(error.value)
def point_trace_matrix(V, TV, x0): ''' Let u in V; u = ck phi_k then u(x0) \in TV = ck phi_k(x0). So this is a 1 by dim(V) matrix where the column values are phi_k(x0). ''' mesh = V.mesh() tree = mesh.bounding_box_tree() cell = tree.compute_first_entity_collision(Point(*x0)) assert cell < mesh.num_cells() # Cell for restriction Vcell = Cell(mesh, cell) vertex_coordinates = Vcell.get_vertex_coordinates() cell_orientation = Vcell.orientation() x0 = np.fromiter(x0, dtype=float) # Columns - get all components at once all_dofs = V.dofmap().cell_dofs(cell).tolist() Vel = V.element() value_size = V.ufl_element().value_size() basis_values = np.zeros(V.element().space_dimension() * value_size) Vel.evaluate_basis_all(basis_values, x0, vertex_coordinates, cell_orientation) with petsc_serial_matrix(TV, V) as mat: # Scalar gets all if value_size == 1: component_dofs = lambda component: V.dofmap().cell_dofs(cell) # Slices else: component_dofs = lambda component: V.sub(component).dofmap( ).cell_dofs(cell) for row in map(int, TV.dofmap().cell_dofs(cell)): # R^n components sub_dofs = component_dofs(row) sub_dofs_local = [all_dofs.index(dof) for dof in sub_dofs] print row, sub_dofs, sub_dofs_local, basis_values[sub_dofs_local] mat.setValues([row], sub_dofs, basis_values[sub_dofs_local], PETSc.InsertMode.INSERT_VALUES) return mat
def write_fenics_file(dim, ofilename): ofile = File(ofilename + '.xml') mesh = Mesh() editor = MeshEditor() editor.open(mesh, dim, dim) editor.init_vertices(nodes.shape[1]) editor.init_cells(len(cell_map)) for i in range(nodes.shape[1]): if dim == 2: editor.add_vertex(i, nodes[0, i], nodes[1, i]) else: editor.add_vertex(i, nodes[0, i], nodes[1, i], nodes[2, i]) for i in range(1, len(cell_map)+1): if dim == 2: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1) else: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1, cell_map[i][3]-1) mesh.order() mvc = mesh.domains().markers(dim-1) for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell-1) nodes_of_cell = dolfin_cell.entities(0) #print cell #print nodes_of_cell nodes_of_face = nds - 1 #print nodes_of_face for jj, ff in enumerate(facets(dolfin_cell)): facet_nodes = ff.entities(0) #print facet_nodes if all(map(lambda x: x in nodes_of_face, facet_nodes)): local_index = jj break mvc.set_value(cell-1, local_index, zone) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def point_trace_matrix(V, TV, x0): ''' Let u in V; u = ck phi_k then u(x0) \in TV = ck phi_k(x0). So this is a 1 by dim(V) matrix where the column values are phi_k(x0). ''' mesh = V.mesh() tree = mesh.bounding_box_tree() cell = tree.compute_first_entity_collision(Point(*x0)) assert cell < mesh.num_cells() # Cell for restriction Vcell = Cell(mesh, cell) vertex_coordinates = Vcell.get_vertex_coordinates() cell_orientation = Vcell.orientation() x0 = np.fromiter(x0, dtype=float) # Columns - get all components at once all_dofs = V.dofmap().cell_dofs(cell).tolist() Vel = V.element() value_size = V.ufl_element().value_size() basis_values = np.zeros(V.element().space_dimension()*value_size) Vel.evaluate_basis_all(basis_values, x0, vertex_coordinates, cell_orientation) with petsc_serial_matrix(TV, V) as mat: # Scalar gets all if value_size == 1: component_dofs = lambda component: V.dofmap().cell_dofs(cell) # Slices else: component_dofs = lambda component: V.sub(component).dofmap().cell_dofs(cell) for row in map(int, TV.dofmap().cell_dofs(cell)): # R^n components sub_dofs = component_dofs(row) sub_dofs_local = [all_dofs.index(dof) for dof in sub_dofs] print row, sub_dofs, sub_dofs_local, basis_values[sub_dofs_local] mat.setValues([row], sub_dofs, basis_values[sub_dofs_local], PETSc.InsertMode.INSERT_VALUES) return mat
def build_grad_matrices(V, points): """Build the sparse m-by-n matrices that map a coefficient set for a function in V to the values of dx and dy at a number m of points. """ # See <https://www.allanswered.com/post/lkbkm/#zxqgk> mesh = V.mesh() bbt = BoundingBoxTree() bbt.build(mesh) dofmap = V.dofmap() el = V.element() rows = [] cols = [] datax = [] datay = [] for i, xy in enumerate(points): cell_id = bbt.compute_first_entity_collision(Point(*xy)) cell = Cell(mesh, cell_id) coordinate_dofs = cell.get_vertex_coordinates() rows.append([i, i, i]) cols.append(dofmap.cell_dofs(cell_id)) v = el.evaluate_basis_derivatives_all(1, xy, coordinate_dofs, cell_id) v = v.reshape(3, 2) datax.append(v[:, 0]) datay.append(v[:, 1]) rows = numpy.concatenate(rows) cols = numpy.concatenate(cols) datax = numpy.concatenate(datax) datay = numpy.concatenate(datay) m = len(points) n = V.dim() dx_matrix = sparse.csr_matrix((datax, (rows, cols)), shape=(m, n)) dy_matrix = sparse.csr_matrix((datay, (rows, cols)), shape=(m, n)) return dx_matrix, dy_matrix
def test_pointsource_vector(mesh): """Tests point source when given constructor PointSource(V, point, mag) with a vector that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor """ cell = Cell(mesh, 0) point = cell.midpoint() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0) == 0
def test_pointsource_vector(mesh): """Tests point source when given constructor PointSource(V, point, mag) with a vector that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor """ cell = Cell(mesh, 0) point = cell.midpoint() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0)*v*dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0) == 0
class FEBasisFunction(UserExpression): '''Evaluator of dof of V on functions''' def __init__(self, V, **kwargs): super().__init__(self, element=V.ufl_element(), **kwargs) self.elm = V.element() self.mesh = V.mesh() is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size()) @property def dof(self): return self.__dof @dof.setter def dof(self, value): assert value < self.elm.space_dimension() self.__dof = value @property def cell(self): return self.__cell @cell.setter def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_ def eval_cell(self, values, x, cell): values[:] = self.elm.evaluate_basis(self.dof, x, self.__cell_vertex_x, self.__cell_orientation) def __call__(self, x): self.eval(self.__values, x) return 1*self.__values
class DegreeOfFreedom(object): '''Evaluator of dof of V on functions''' def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 @property def dof(self): return self.__dof @dof.setter def dof(self, value): assert value < self.elm.space_dimension() self.__dof = value @property def cell(self): return self.__cell @cell.setter def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_ def eval(self, f): return self.elm.evaluate_dofs(f, self.__cell_vertex_x, self.__cell_orientation, self.__cell)[self.dof] def eval_dofs(self, f): return self.elm.evaluate_dofs(f, self.__cell_vertex_x, self.__cell_orientation, self.__cell)
def test_simplex(self): print('\n== Testing DOFs ====') for dim, p in itertools.product([2, 3], range(1, 6)): print('dim={}; p={}'.format(dim, p)) mesh = get_reference_element(dim) W = FunctionSpace(mesh, "DG", p) cell = Cell(mesh, 0) dofs = W.element().tabulate_dof_coordinates(cell) dofs2 = get_dof_coordinates(dim, pol_order=p) dofs = dofs[np.lexsort(dofs.T)] dofs2 = dofs2[np.lexsort(dofs2.T)] self.assertAlmostEqual(0, np.linalg.norm(dofs - dofs2), delta=1e-14) self.assertAlmostEqual(W.element().space_dimension(), dimP(dim, p), delta=1e-13) print('...ok')
def test_issue_568(): mesh = UnitSquareMesh(MPI.comm_self, 4, 4) cell = Cell(mesh, 0) # This no longer fails because serial mesh now is building facets, using # same pipeline as parallel. # Should throw an error, not just segfault (only works in DEBUG mode!) with pytest.raises(RuntimeError): cell.facet_area(0) # Should work after initializing the connectivity mesh.init(2, 1) cell.facet_area(0)
class DegreeOfFreedom(object): '''Evaluator of dof of V on functions''' def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 @property def dof(self): return self.__dof @dof.setter def dof(self, value): assert value < self.elm.space_dimension() self.__dof = value @property def cell(self): return self.__cell @cell.setter def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_ def eval(self, f): return self.elm.evaluate_dof(self.dof, f.as_expression() if isinstance(f, FEBasisFunction) else f, self.__cell_vertex_x, self.__cell_orientation, self.__cell)
def __init__(self, V): self.elm = V.element() self.mesh = V.mesh() shape = V.ufl_element().value_shape() degree = V.ufl_element().degree() # A fake instanc to talk to with the world adapter = type('MiroHack', (Expression, ), {'value_shape': lambda self_, : shape, 'eval': lambda self_, values, x: self.eval(values, x)}) self.__adapter = adapter(degree=degree) is_1d_in_3d = self.mesh.topology().dim() == 1 and self.mesh.geometry().dim() == 3 self.orient_cell = cell_orientation(is_1d_in_3d) # Allocs self.__cell = Cell(self.mesh, 0) self.__cell_vertex_x = self.__cell.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(self.__cell) self.__dof = 0 self.__values = np.zeros(V.ufl_element().value_size())
def _single_mesh_entity_plot(self, cell_index, tdim): 'Plot labels of mesh entities of topological dim. that are in cell.' # Compute cell->entity connectivity unless cell-cell. Don't need patch if self.tdim == tdim: entity_indices = [cell_index] else: entity_indices = Cell(self.mesh, cell_index).entities(tdim) color = self.mesh_entity_colors[tdim] labels = self.mesh_entity_labels[tdim] # Loop through entities of the cell for entity_index in entity_indices: entity = MeshEntity(self.mesh, tdim, entity_index) # Midpoint is label location x = entity.midpoint() x = [x[i] for i in range(self.gdim)] if (self.order == 'global') and self.mpi_size > 1: args = x + [str(entity.global_index())] else: args = x + [str(entity_index)] # Create new label if entitiy not labeled already if not (entity_index in labels): labels[entity_index] = self.axes.text(*args, color=color)
def test_ghost_connectivities(mode): # Ghosted mesh meshG = UnitSquareMesh(MPI.comm_world, 4, 4, ghost_mode=mode) meshG.init(1, 2) # Reference mesh, not ghosted, not parallel meshR = UnitSquareMesh(MPI.comm_self, 4, 4, ghost_mode=cpp.mesh.GhostMode.none) meshR.init(1, 2) # Create reference mapping from facet midpoint to cell midpoint reference = {} for facet in Facets(meshR): fidx = facet.index() facet_mp = tuple(facet.midpoint()[:]) reference[facet_mp] = [] for cidx in meshR.topology.connectivity(1, 2)(fidx): cell = Cell(meshR, cidx) cell_mp = tuple(cell.midpoint()[:]) reference[facet_mp].append(cell_mp) # Loop through ghosted mesh and check connectivities allowable_cell_indices = [ c.index() for c in Cells(meshG, cpp.mesh.MeshRangeType.ALL) ] for facet in Facets(meshG, cpp.mesh.MeshRangeType.REGULAR): fidx = facet.index() facet_mp = tuple(facet.midpoint()[:]) assert facet_mp in reference for cidx in meshG.topology.connectivity(1, 2)(fidx): assert cidx in allowable_cell_indices cell = Cell(meshG, cidx) cell_mp = tuple(cell.midpoint()[:]) assert cell_mp in reference[facet_mp]
def cell(self, value): cell_ = Cell(self.mesh, value) self.__cell_vertex_x[:] = cell_.get_vertex_coordinates() self.__cell_orientation = self.orient_cell(cell_) self.__cell = cell_
def cylinder_average_matrix(V, TV, radius, quad_degree): '''Averaging matrix''' mesh = V.mesh() line_mesh = TV.mesh() # We are going to perform the integration with Gauss quadrature at # the end (PI u)(x): # A cell of mesh (an edge) defines a normal vector. Let P be the plane # that is defined by the normal vector n and some point x on Gamma. Let L # be the circle that is the intersect of P and S. The value of q (in Q) at x # is defined as # # q(x) = (1/|L|)*\int_{L}g(x)*dL # # which simplifies to g(x) = (1/(2*pi*R))*\int_{-pi}^{pi}u(L)*R*d(theta) and # or = (1/2) * \int_{-1}^{1} u (L(pi*s)) * ds # This can be integrated no problemo once we figure out L. To this end, let # t_1 and t_2 be two unit mutually orthogonal vectors that are orthogonal to # n. Then L(pi*s) = p + R*t_1*cos(pi*s) + R*t_2*sin(pi*s) can be seen to be # such that i) |x-p| = R and ii) x.n = 0 [i.e. this the suitable # parametrization] # Clearly we can scale the weights as well as precompute # cos and sin terms. xq, wq = leggauss(quad_degree) wq *= 0.5 cos_xq = np.cos(np.pi*xq).reshape((-1, 1)) sin_xq = np.sin(np.pi*xq).reshape((-1, 1)) if is_number(radius): radius = lambda x, radius=radius: radius mesh_x = TV.mesh().coordinates() # The idea for point evaluation/computing dofs of TV is to minimize # the number of evaluation. I mean a vector dof if done naively would # have to evaluate at same x number of component times. value_size = TV.ufl_element().value_size() # Eval at points will require serch tree = mesh.bounding_box_tree() limit = mesh.num_cells() TV_coordinates = TV.tabulate_dof_coordinates().reshape((TV.dim(), -1)) TV_dm = TV.dofmap() V_dm = V.dofmap() # For non scalar we plan to make compoenents by shift if value_size > 1: TV_dm = TV.sub(0).dofmap() Vel = V.element() basis_values = np.zeros(V.element().space_dimension()*value_size) with petsc_serial_matrix(TV, V) as mat: for line_cell in cells(line_mesh): # Get the tangent => orthogonal tangent vectors v0, v1 = mesh_x[line_cell.entities(0)] n = v0 - v1 t1 = np.array([n[1]-n[2], n[2]-n[0], n[0]-n[1]]) t2 = np.cross(n, t1) t1 /= np.linalg.norm(t1) t2 = t2/np.linalg.norm(t2) # The idea is now to minimize the point evaluation scalar_dofs = TV_dm.cell_dofs(line_cell.index()) scalar_dofs_x = TV_coordinates[scalar_dofs] for scalar_row, avg_point in zip(scalar_dofs, scalar_dofs_x): # Get radius and integration points rad = radius(avg_point) integration_points = avg_point + rad*t1*sin_xq + rad*t2*cos_xq data = {} for index, ip in enumerate(integration_points): c = tree.compute_first_entity_collision(Point(*ip)) if c >= limit: continue Vcell = Cell(mesh, c) vertex_coordinates = Vcell.get_vertex_coordinates() cell_orientation = Vcell.orientation() Vel.evaluate_basis_all(basis_values, ip, vertex_coordinates, cell_orientation) cols_ip = V_dm.cell_dofs(c) values_ip = basis_values*wq[index] # Add for col, value in zip(cols_ip, values_ip.reshape((-1, value_size))): if col in data: data[col] += value else: data[col] = value # The thing now that with data we can assign to several # rows of the matrix column_indices = np.array(data.keys(), dtype='int32') for shift in range(value_size): row = scalar_row + shift column_values = np.array([data[col][shift] for col in column_indices]) mat.setValues([row], column_indices, column_values, PETSc.InsertMode.INSERT_VALUES) # On to next avg point # On to next cell return PETScMatrix(mat)
def sphere_average_matrix(V, TV, radius, quad_degree): '''Averaging matrix over the sphere''' mesh = V.mesh() line_mesh = TV.mesh() # Lebedev below need off degrees if quad_degree % 2 == 0: quad_degree += 1 # NOTE: this is a dependency from quadpy.sphere import Lebedev integrator = Lebedev(quad_degree) xq = integrator.points wq = integrator.weights if is_number(radius): radius = lambda x, radius=radius: radius mesh_x = TV.mesh().coordinates() # The idea for point evaluation/computing dofs of TV is to minimize # the number of evaluation. I mean a vector dof if done naively would # have to evaluate at same x number of component times. value_size = TV.ufl_element().value_size() # Eval at points will require serch tree = mesh.bounding_box_tree() limit = mesh.num_cells() TV_coordinates = TV.tabulate_dof_coordinates().reshape((TV.dim(), -1)) TV_dm = TV.dofmap() V_dm = V.dofmap() # For non scalar we plan to make compoenents by shift if value_size > 1: TV_dm = TV.sub(0).dofmap() Vel = V.element() basis_values = np.zeros(V.element().space_dimension()*value_size) with petsc_serial_matrix(TV, V) as mat: for line_cell in cells(line_mesh): # The idea is now to minimize the point evaluation scalar_dofs = TV_dm.cell_dofs(line_cell.index()) scalar_dofs_x = TV_coordinates[scalar_dofs] for scalar_row, avg_point in zip(scalar_dofs, scalar_dofs_x): # Get radius and integration points rad = radius(avg_point) # Scale and shift the unit sphere to the point integration_points = xq*rad + avg_point data = {} for index, ip in enumerate(integration_points): c = tree.compute_first_entity_collision(Point(*ip)) if c >= limit: continue Vcell = Cell(mesh, c) vertex_coordinates = Vcell.get_vertex_coordinates() cell_orientation = Vcell.orientation() Vel.evaluate_basis_all(basis_values, ip, vertex_coordinates, cell_orientation) cols_ip = V_dm.cell_dofs(c) values_ip = basis_values*wq[index] # Add for col, value in zip(cols_ip, values_ip.reshape((-1, value_size))): if col in data: data[col] += value else: data[col] = value # The thing now that with data we can assign to several # rows of the matrix column_indices = np.array(data.keys(), dtype='int32') for shift in range(value_size): row = scalar_row + shift column_values = np.array([data[col][shift] for col in column_indices]) mat.setValues([row], column_indices, column_values, PETSc.InsertMode.INSERT_VALUES) # On to next avg point # On to next cell return PETScMatrix(mat)
def trace_3d1d_matrix(V, TV, reduced_mesh): '''Trace from 3d to 1d. Makes sense only for CG space''' assert reduced_mesh.id() == TV.mesh().id() assert V.ufl_element().family() == 'Lagrange' mesh = V.mesh() line_mesh = TV.mesh() # The idea for point evaluation/computing dofs of TV is to minimize # the number of evaluation. I mean a vector dof if done naively would # have to evaluate at same x number of component times. value_size = TV.ufl_element().value_size() # We use the map to get (1d cell -> [3d edge) -> 3d cell] if hasattr(reduced_mesh, 'parent_entity_map'): # ( ) mapping = reduced_mesh.parent_entity_map[mesh.id()][1] # [ ] mesh.init(1) mesh.init(1, 3) e2c = mesh.topology()(1, 3) # From 1d cell (by index) get_cell3d = lambda c, d1d3=mapping, d3d3=e2c: d3d3(d1d3[c.index()])[0] # Tree collision by midpoint else: tree = mesh.bounding_box_tree() limit = mesh.num_cells() get_cell3d = lambda c, tree=tree, bound=limit: ( lambda index: index if index<bound else None )(tree.compute_first_entity_collision(c.midpoint())) TV_coordinates = TV.tabulate_dof_coordinates().reshape((TV.dim(), -1)) TV_dm = TV.dofmap() V_dm = V.dofmap() # For non scalar we plan to make compoenents by shift if value_size > 1: TV_dm = TV.sub(0).dofmap() Vel = V.element() basis_values = np.zeros(V.element().space_dimension()*value_size) with petsc_serial_matrix(TV, V) as mat: for line_cell in cells(line_mesh): # Get the tangent => orthogonal tangent vectors # The idea is now to minimize the point evaluation scalar_dofs = TV_dm.cell_dofs(line_cell.index()) scalar_dofs_x = TV_coordinates[scalar_dofs] # Let's get a 3d cell to use for getting the V values # CG assumption allows taking any tet_cell = get_cell3d(line_cell) if tet_cell is None: continue Vcell = Cell(mesh, tet_cell) vertex_coordinates = Vcell.get_vertex_coordinates() cell_orientation = 0 # Columns are determined by V cell! I guess the sparsity # could be improved if for x_dofs of TV only x_dofs of V # were considered column_indices = np.array(V_dm.cell_dofs(tet_cell), dtype='int32') for scalar_row, avg_point in zip(scalar_dofs, scalar_dofs_x): # 3d at point Vel.evaluate_basis_all(basis_values, avg_point, vertex_coordinates, cell_orientation) # The thing now is that with data we can assign to several # rows of the matrix. Shift determines the (x, y, ... ) or # (xx, xy, yx, ...) component of Q data = basis_values.reshape((-1, value_size)).T for shift, column_values in enumerate(data): row = scalar_row + shift mat.setValues([row], column_indices, column_values, PETSc.InsertMode.INSERT_VALUES) # On to next avg point # On to next cell return PETScMatrix(mat)
def foo(cell_index): # get the midpoint as array cell = Cell(self.mesh, cell_index) midpoint = cell.midpoint() return [midpoint.x(), midpoint.y()]