pub struct SingleElementMeshBuilder<T: Scalar> { /* private fields */ }Expand description
Mesh builder for a single element mesh
The following gives an example of creating a new mesh consisting of a single triangle.
use ndmesh::traits::Builder;
use ndmesh::SingleElementMeshBuilder;
use ndelement::types::ReferenceCellType;
// The geometric dimension of our space is 3.
let gdim = 3;
// We are building a two dimensional surface triangle mesh within a three dimensional space.
// Our mesh will have three points and one `Triangle` cell of order 1.
let mut builder = SingleElementMeshBuilder::new_with_capacity(gdim, 3, 1, (ReferenceCellType::Triangle, 1));
builder.add_point(0, &[0.0, 0.0, 0.0]);
builder.add_point(1, &[1.0, 0.0, 0.0]);
builder.add_point(2, &[0.0, 1.0, 0.0]);
builder.add_cell(0, &[0, 1, 2]);
let mesh = builder.create_mesh();Implementations§
Source§impl<T: Scalar> SingleElementMeshBuilder<T>
impl<T: Scalar> SingleElementMeshBuilder<T>
Sourcepub fn new(gdim: usize, data: (ReferenceCellType, usize)) -> Self
pub fn new(gdim: usize, data: (ReferenceCellType, usize)) -> Self
Create a new mesh builder
Examples found in repository?
ndmesh/examples/single_element_mesh.rs (line 13)
10fn main() {
11 // When creating the mesh builder, we give the physical/geometric dimension (3) and the cell type
12 // and degree of the element
13 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Quadrilateral, 1));
14 // Add six points with ids 0 to 5
15 b.add_point(0, &[0.0, 0.0, 0.0]);
16 b.add_point(1, &[1.0, 0.0, 0.0]);
17 b.add_point(2, &[2.0, 0.0, 0.2]);
18 b.add_point(3, &[0.0, 1.0, 0.0]);
19 b.add_point(4, &[1.0, 1.0, -0.2]);
20 b.add_point(5, &[2.0, 1.0, 0.0]);
21 // Add two cells
22 b.add_cell(0, &[0, 1, 3, 4]);
23 b.add_cell(1, &[1, 2, 4, 5]);
24 // Create the mesh
25 let mesh = b.create_mesh();
26
27 // Print the coordinates or each point in the mesh
28 let mut coords = vec![0.0; mesh.geometry_dim()];
29 for point in mesh.entity_iter(ReferenceCellType::Point) {
30 point.geometry().points().collect::<Vec<_>>()[0].coords(coords.as_mut_slice());
31 println!("point {}: {:#?}", point.local_index(), coords);
32 }
33
34 // Print the vertices of each cell
35 for cell in mesh.entity_iter(ReferenceCellType::Quadrilateral) {
36 println!(
37 "cell {}: {:?} ",
38 cell.local_index(),
39 cell.topology()
40 .sub_entity_iter(ReferenceCellType::Point)
41 .collect::<Vec<_>>()
42 );
43 }
44}More examples
ndmesh/examples/parallel_io.rs (line 29)
17fn main() {
18 let universe: Universe = mpi::initialize().unwrap();
19 let comm = universe.world();
20 let rank = comm.rank();
21
22 let g = if rank == 0 {
23 // Create a mesh using the shapes module: unit_cube_boundary will mesh the surface of a cube
24 let serial_g = shapes::unit_cube_boundary::<f64>(4, 5, 4, ReferenceCellType::Triangle);
25
26 // Distribute this mesh across processes
27 serial_g.distribute(&comm, GraphPartitioner::None)
28 } else {
29 let b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
30 b.create_parallel_mesh(&comm, 0)
31 };
32
33 // If the serde option is used, the raw mesh data can be exported in RON format
34 g.export_as_ron("_unit_cube_boundary_parallel.ron");
35
36 // Wait for export to finish
37 comm.barrier();
38
39 // A mesh can be re-imported from raw RON data. Note that it must be imported on the same number of processes as it was exported using
40 let g2 = ParallelMeshImpl::<'_, _, SingleElementMesh::<f64, CiarletElement<f64, IdentityMap, f64>>>::import_from_ron(&comm, "_unit_cube_boundary_parallel.ron");
41
42 // Print the first 5 cells of each mesh on process 0
43 if rank == 0 {
44 println!("The first 5 cells of the mesh");
45 for (cell, cell2) in izip!(
46 g.local_mesh().entity_iter(ReferenceCellType::Triangle),
47 g2.local_mesh().entity_iter(ReferenceCellType::Triangle)
48 )
49 .take(5)
50 {
51 println!(
52 "{:?} {:?}",
53 cell.topology()
54 .sub_entity_iter(ReferenceCellType::Point)
55 .collect::<Vec<_>>(),
56 cell2
57 .topology()
58 .sub_entity_iter(ReferenceCellType::Point)
59 .collect::<Vec<_>>(),
60 );
61 }
62 }
63}ndmesh/examples/io.rs (line 53)
13fn main() {
14 // Create a mesh using the shapes module: unit_cube_boundary will mesh the surface of a cube
15 let g = shapes::unit_cube_boundary::<f64>(4, 5, 4, ReferenceCellType::Triangle);
16
17 // If the serde option is used, the raw mesh data can be exported in RON format
18 g.export_as_ron("_unit_cube_boundary.ron");
19
20 // A mesh can be re-imported from raw RON data
21 let g2 = SingleElementMesh::<f64, CiarletElement<f64, IdentityMap, f64>>::import_from_ron(
22 "_unit_cube_boundary.ron",
23 );
24
25 // Print the first 5 cells of each mesh
26 println!("The first 5 cells of the meshes");
27 for (cell, cell2) in izip!(
28 g.entity_iter(ReferenceCellType::Triangle),
29 g2.entity_iter(ReferenceCellType::Triangle)
30 )
31 .take(5)
32 {
33 println!(
34 "{:?} {:?}",
35 cell.topology()
36 .sub_entity_iter(ReferenceCellType::Point)
37 .collect::<Vec<_>>(),
38 cell2
39 .topology()
40 .sub_entity_iter(ReferenceCellType::Point)
41 .collect::<Vec<_>>(),
42 );
43 }
44
45 println!();
46
47 // Alternatively, meshes can be exported and imported to/from Gmsh files
48
49 // Export the mesh as a Gmsh .msh file
50 g.export_as_gmsh("_unit_cube_boundary.msh");
51
52 // To import from a Gmsh .msh file, a builder is used
53 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
54 b.import_from_gmsh("_unit_cube_boundary.msh");
55 let g3 = b.create_mesh();
56
57 // Print the first 5 cells of each mesh
58 println!("The first 5 cells of the meshes");
59 for (cell, cell3) in izip!(
60 g.entity_iter(ReferenceCellType::Triangle),
61 g3.entity_iter(ReferenceCellType::Triangle)
62 )
63 .take(5)
64 {
65 println!(
66 "{:?} {:?}",
67 cell.topology()
68 .sub_entity_iter(ReferenceCellType::Point)
69 .collect::<Vec<_>>(),
70 cell3
71 .topology()
72 .sub_entity_iter(ReferenceCellType::Point)
73 .collect::<Vec<_>>(),
74 );
75 }
76}ndmesh/examples/test_push_forward.rs (line 16)
15fn test_lagrange_push_forward() {
16 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
17 b.add_point(0, &[0.0, 0.0, 0.0]);
18 b.add_point(1, &[1.0, 0.0, 0.0]);
19 b.add_point(2, &[2.0, 0.0, 1.0]);
20 b.add_point(3, &[0.0, 1.0, 0.0]);
21 b.add_cell(0, &[0, 1, 3]);
22 b.add_cell(1, &[1, 2, 3]);
23 let mesh = b.create_mesh();
24
25 let e = lagrange::create::<f64, f64>(
26 ReferenceCellType::Triangle,
27 4,
28 Continuity::Standard,
29 lagrange::LagrangeVariant::Equispaced,
30 );
31
32 let npts = 5;
33
34 let mut cell0_points = rlst_dynamic_array!(f64, [2, npts]);
35 for i in 0..npts {
36 cell0_points[[1, i]] = i as f64 / (npts - 1) as f64;
37 cell0_points[[0, i]] = 1.0 - cell0_points[[1, i]];
38 }
39 let mut cell0_table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
40 e.tabulate(&cell0_points, 0, &mut cell0_table);
41
42 let mut points = rlst_dynamic_array!(f64, [2, npts]);
43 for i in 0..npts {
44 points[[0, i]] = 0.0;
45 points[[1, i]] = i as f64 / (npts - 1) as f64;
46 }
47
48 let mut table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
49 e.tabulate(&points, 0, &mut table);
50
51 let gmap = mesh.geometry_map(ReferenceCellType::Triangle, 1, &points);
52
53 let mut jacobians = rlst_dynamic_array!(f64, [mesh.geometry_dim(), mesh.topology_dim(), npts]);
54 let mut jinv = rlst_dynamic_array!(f64, [mesh.topology_dim(), mesh.geometry_dim(), npts]);
55 let mut jdets = vec![0.0; npts];
56
57 gmap.jacobians_inverses_dets(1, &mut jacobians, &mut jinv, &mut jdets);
58
59 let mut cell1_table = DynArray::<f64, 4>::from_shape(table.shape());
60 e.push_forward(&table, 0, &jacobians, &jdets, &jinv, &mut cell1_table);
61
62 // Check that basis functions are continuous between cells
63 for (cell0_dof, cell1_dof) in izip!(
64 e.entity_closure_dofs(1, 1).unwrap(),
65 e.entity_closure_dofs(1, 2).unwrap()
66 ) {
67 for i in 0..npts {
68 assert_relative_eq!(
69 cell0_table[[0, i, *cell0_dof, 0]],
70 cell1_table[[0, i, *cell1_dof, 0]],
71 epsilon = 1e-10
72 );
73 }
74 }
75}
76
77/// Test Ravaiart-Thomas push forward
78fn test_rt_push_forward() {
79 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
80 b.add_point(0, &[0.0, 0.0, 0.0]);
81 b.add_point(1, &[1.0, 0.0, 0.0]);
82 b.add_point(2, &[2.0, 0.0, 1.0]);
83 b.add_point(3, &[0.0, 1.0, 0.0]);
84 b.add_cell(0, &[0, 1, 3]);
85 b.add_cell(1, &[1, 2, 3]);
86 let mesh = b.create_mesh();
87
88 let e =
89 raviart_thomas::create::<f64, f64>(ReferenceCellType::Triangle, 4, Continuity::Standard);
90
91 let npts = 5;
92
93 let mut cell0_points = rlst_dynamic_array!(f64, [2, npts]);
94 for i in 0..npts {
95 cell0_points[[1, i]] = i as f64 / (npts - 1) as f64;
96 cell0_points[[0, i]] = 1.0 - cell0_points[[1, i]];
97 }
98 let mut cell0_table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
99 e.tabulate(&cell0_points, 0, &mut cell0_table);
100
101 let mut points = rlst_dynamic_array!(f64, [2, npts]);
102 for i in 0..npts {
103 points[[0, i]] = 0.0;
104 points[[1, i]] = i as f64 / (npts - 1) as f64;
105 }
106
107 let mut table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
108 e.tabulate(&points, 0, &mut table);
109
110 let gmap = mesh.geometry_map(ReferenceCellType::Triangle, 1, &points);
111
112 let mut jacobians = rlst_dynamic_array!(f64, [mesh.geometry_dim(), mesh.topology_dim(), npts]);
113 let mut jinv = rlst_dynamic_array!(f64, [mesh.topology_dim(), mesh.geometry_dim(), npts]);
114 let mut jdets = vec![0.0; npts];
115
116 gmap.jacobians_inverses_dets(1, &mut jacobians, &mut jinv, &mut jdets);
117
118 let mut cell1_table =
119 DynArray::<f64, 4>::from_shape([table.shape()[0], table.shape()[1], table.shape()[2], 3]);
120 e.push_forward(&table, 0, &jacobians, &jdets, &jinv, &mut cell1_table);
121
122 // Check that basis functions dotted with normal to edge are continuous between cells
123 for (cell0_dof, cell1_dof) in izip!(
124 e.entity_closure_dofs(1, 2).unwrap(),
125 e.entity_closure_dofs(1, 1).unwrap()
126 ) {
127 for i in 0..npts {
128 assert_relative_eq!(
129 (cell0_table[[0, i, *cell0_dof, 0]] + cell0_table[[0, i, *cell0_dof, 1]])
130 / f64::sqrt(2.0),
131 (cell1_table[[0, i, *cell1_dof, 0]]
132 + cell1_table[[0, i, *cell1_dof, 1]]
133 + 2.0 * cell1_table[[0, i, *cell1_dof, 2]])
134 / f64::sqrt(6.0),
135 epsilon = 1e-10
136 );
137 }
138 }
139}
140
141/// Test Nedelec push forward
142fn test_nc_push_forward() {
143 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
144 b.add_point(0, &[0.0, 0.0, 0.0]);
145 b.add_point(1, &[1.0, 0.0, 0.0]);
146 b.add_point(2, &[2.0, 0.0, 1.0]);
147 b.add_point(3, &[0.0, 1.0, 0.0]);
148 b.add_cell(0, &[0, 1, 3]);
149 b.add_cell(1, &[1, 2, 3]);
150 let mesh = b.create_mesh();
151
152 let e = nedelec::create::<f64, f64>(ReferenceCellType::Triangle, 4, Continuity::Standard);
153
154 let npts = 5;
155
156 let mut cell0_points = rlst_dynamic_array!(f64, [2, npts]);
157 for i in 0..npts {
158 cell0_points[[1, i]] = i as f64 / (npts - 1) as f64;
159 cell0_points[[0, i]] = 1.0 - cell0_points[[1, i]];
160 }
161 let mut cell0_table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
162 e.tabulate(&cell0_points, 0, &mut cell0_table);
163
164 let mut points = rlst_dynamic_array!(f64, [2, npts]);
165 for i in 0..npts {
166 points[[0, i]] = 0.0;
167 points[[1, i]] = i as f64 / (npts - 1) as f64;
168 }
169
170 let mut table = DynArray::<f64, 4>::from_shape(e.tabulate_array_shape(0, npts));
171 e.tabulate(&points, 0, &mut table);
172
173 let gmap = mesh.geometry_map(ReferenceCellType::Triangle, 1, &points);
174
175 let mut jacobians = rlst_dynamic_array!(f64, [mesh.geometry_dim(), mesh.topology_dim(), npts]);
176 let mut jinv = rlst_dynamic_array!(f64, [mesh.topology_dim(), mesh.geometry_dim(), npts]);
177 let mut jdets = vec![0.0; npts];
178
179 gmap.jacobians_inverses_dets(1, &mut jacobians, &mut jinv, &mut jdets);
180
181 let mut cell1_table =
182 DynArray::<f64, 4>::from_shape([table.shape()[0], table.shape()[1], table.shape()[2], 3]);
183 e.push_forward(&table, 0, &jacobians, &jdets, &jinv, &mut cell1_table);
184
185 // Check that basis functions dotted with tangent to edge are continuous between cells
186 for (cell0_dof, cell1_dof) in izip!(
187 e.entity_closure_dofs(1, 2).unwrap(),
188 e.entity_closure_dofs(1, 1).unwrap()
189 ) {
190 for i in 0..npts {
191 assert_relative_eq!(
192 (cell0_table[[0, i, *cell0_dof, 0]] - cell0_table[[0, i, *cell0_dof, 1]])
193 / f64::sqrt(2.0),
194 (cell1_table[[0, i, *cell1_dof, 0]] - cell1_table[[0, i, *cell1_dof, 1]])
195 / f64::sqrt(2.0),
196 epsilon = 1e-10
197 );
198 }
199 }
200}ndmesh/examples/test_parallel_mesh.rs (line 20)
17fn run_partitioner_test<C: Communicator>(comm: &C, partitioner: GraphPartitioner) {
18 let n = 10;
19
20 let mut b = SingleElementMeshBuilder::<f64>::new(2, (ReferenceCellType::Quadrilateral, 1));
21
22 let rank = comm.rank();
23 let mesh = if rank == 0 {
24 let mut i = 0;
25 for y in 0..n {
26 for x in 0..n {
27 b.add_point(i, &[x as f64 / (n - 1) as f64, y as f64 / (n - 1) as f64]);
28 i += 1;
29 }
30 }
31
32 let mut i = 0;
33 for y in 0..n - 1 {
34 for x in 0..n - 1 {
35 let sw = n * y + x;
36 b.add_cell(i, &[sw, sw + 1, sw + n, sw + n + 1]);
37 i += 1;
38 }
39 }
40
41 b.create_parallel_mesh_root(comm, partitioner)
42 } else {
43 b.create_parallel_mesh(comm, 0)
44 };
45
46 // Check that owned cells are sorted ahead of ghost cells
47 let cell_count_owned = mesh
48 .local_mesh()
49 .entity_iter(ReferenceCellType::Quadrilateral)
50 .filter(|entity| entity.is_owned())
51 .count();
52
53 // Check that the first `cell_count_owned` entities are actually owned.
54 for cell in mesh
55 .local_mesh()
56 .entity_iter(ReferenceCellType::Quadrilateral)
57 .take(cell_count_owned)
58 {
59 assert!(cell.is_owned())
60 }
61
62 // Make sure that the indices of the global cells are in consecutive order
63 for (cell_global_count, cell) in izip!(
64 mesh.cell_layout().local_range().0..,
65 mesh.local_mesh()
66 .entity_iter(ReferenceCellType::Quadrilateral)
67 .take(cell_count_owned)
68 ) {
69 assert_eq!(cell.global_index(), cell_global_count);
70 }
71
72 // Get the global indices.
73
74 let global_vertices = mesh
75 .local_mesh()
76 .entity_iter(ReferenceCellType::Point)
77 .filter(|e| matches!(e.ownership(), Ownership::Owned))
78 .map(|e| e.global_index())
79 .collect::<Vec<_>>();
80
81 let nvertices = global_vertices.len();
82
83 let global_cells = mesh
84 .local_mesh()
85 .entity_iter(ReferenceCellType::Quadrilateral)
86 .filter(|e| matches!(e.ownership(), Ownership::Owned))
87 .map(|e| e.global_index())
88 .collect::<Vec<_>>();
89
90 let ncells = global_cells.len();
91
92 let mut total_cells: usize = 0;
93 let mut total_vertices: usize = 0;
94
95 comm.all_reduce_into(&ncells, &mut total_cells, SystemOperation::sum());
96 comm.all_reduce_into(&nvertices, &mut total_vertices, SystemOperation::sum());
97
98 assert_eq!(total_cells, (n - 1) * (n - 1));
99 assert_eq!(total_vertices, n * n);
100}
101
102fn create_single_element_mesh_data(b: &mut SingleElementMeshBuilder<f64>, n: usize) {
103 for y in 0..n {
104 for x in 0..n {
105 b.add_point(
106 y * n + x,
107 &[x as f64 / (n - 1) as f64, y as f64 / (n - 1) as f64, 0.0],
108 );
109 }
110 }
111
112 for i in 0..n - 1 {
113 for j in 0..n - 1 {
114 b.add_cell(
115 i * (n - 1) + j,
116 &[j * n + i, j * n + i + 1, j * n + i + n, j * n + i + n + 1],
117 );
118 }
119 }
120}
121
122fn example_single_element_mesh<C: Communicator>(
123 comm: &C,
124 n: usize,
125) -> ParallelMeshImpl<'_, C, SingleElementMesh<f64, CiarletElement<f64, IdentityMap, f64>>> {
126 let rank = comm.rank();
127
128 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Quadrilateral, 1));
129
130 if rank == 0 {
131 create_single_element_mesh_data(&mut b, n);
132 b.create_parallel_mesh_root(comm, GraphPartitioner::None)
133 } else {
134 b.create_parallel_mesh(comm, 0)
135 }
136}
137
138/// Test that meshes can be exported as RON in parallel
139fn test_parallel_export<C: Communicator>(comm: &C) {
140 let size = comm.size();
141
142 let n = 10;
143 let mesh = example_single_element_mesh(comm, n);
144 let filename = format!("_examples_parallel_io_{size}ranks.ron");
145 mesh.export_as_ron(&filename);
146}
147
148/// Test that meshes can be imported from RON in parallel
149fn test_parallel_import<C: Communicator>(comm: &C) {
150 use ndmesh::traits::ParallelMesh;
151
152 let size = comm.size();
153
154 let filename = format!("_examples_parallel_io_{size}ranks.ron");
155 let mesh = ParallelMeshImpl::<
156 '_,
157 C,
158 SingleElementMesh<f64, CiarletElement<f64, IdentityMap, f64>>,
159 >::import_from_ron(comm, &filename);
160
161 let n = 10;
162 let mesh2 = example_single_element_mesh(comm, n);
163
164 assert_eq!(
165 mesh.local_mesh().entity_count(ReferenceCellType::Point),
166 mesh2.local_mesh().entity_count(ReferenceCellType::Point)
167 );
168}
169
170/// Test that using non-contiguous numbering does not cause panic
171fn test_noncontiguous_numbering<C: Communicator>(comm: &C) {
172 let rank = comm.rank();
173 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Quadrilateral, 1));
174
175 let g = if rank == 0 {
176 let n = 5;
177 for y in 0..n {
178 for x in 0..n {
179 b.add_point(
180 2 * (y * n + x) + 5,
181 &[x as f64 / (n - 1) as f64, y as f64 / (n - 1) as f64, 0.0],
182 );
183 }
184 }
185
186 for i in 0..n - 1 {
187 for j in 0..n - 1 {
188 b.add_cell(
189 3 * (i * (n - 1) + j),
190 &[
191 2 * (j * n + i) + 5,
192 2 * (j * n + i + 1) + 5,
193 2 * (j * n + i + n) + 5,
194 2 * (j * n + i + n + 1) + 5,
195 ],
196 );
197 }
198 }
199
200 b.create_parallel_mesh_root(comm, GraphPartitioner::None)
201 } else {
202 b.create_parallel_mesh(comm, 0)
203 };
204
205 assert!(g.local_mesh().entity_count(ReferenceCellType::Point) > 0);
206}ndmesh/examples/parallel_mesh.rs (line 16)
14fn main() {
15 // The SingleElementMeshBuilder is used to create the mesh
16 let mut b = SingleElementMeshBuilder::<f64>::new(2, (ReferenceCellType::Quadrilateral, 1));
17
18 let universe: Universe = mpi::initialize().unwrap();
19 let comm = universe.world();
20 let rank = comm.rank();
21
22 // Add points and cells to the builder on process 0
23 let n = 10;
24 let mesh = if rank == 0 {
25 let mut i = 0;
26 for y in 0..n {
27 for x in 0..n {
28 b.add_point(i, &[x as f64 / (n - 1) as f64, y as f64 / (n - 1) as f64]);
29 i += 1;
30 }
31 }
32
33 let mut i = 0;
34 for y in 0..n - 1 {
35 for x in 0..n - 1 {
36 let sw = n * y + x;
37 b.add_cell(i, &[sw, sw + 1, sw + n, sw + n + 1]);
38 i += 1;
39 }
40 }
41
42 // Distribute the mesh
43 // In this example, we use Scotch to partition the mesh into pieces to be handles by each process
44 b.create_parallel_mesh_root(&comm, GraphPartitioner::Scotch)
45 } else {
46 // receice the mesh
47 b.create_parallel_mesh(&comm, 0)
48 };
49
50 // Check that owned cells are sorted ahead of ghost cells
51 let cell_count_owned = mesh
52 .local_mesh()
53 .entity_iter(ReferenceCellType::Quadrilateral)
54 .filter(|entity| entity.is_owned())
55 .count();
56
57 // Now check that the first `cell_count_owned` entities are actually owned.
58 for cell in mesh
59 .local_mesh()
60 .entity_iter(ReferenceCellType::Quadrilateral)
61 .take(cell_count_owned)
62 {
63 assert!(cell.is_owned())
64 }
65
66 // Now make sure that the indices of the global cells are in consecutive order
67 for (cell_global_count, cell) in izip!(
68 mesh.cell_layout().local_range().0..,
69 mesh.local_mesh()
70 .entity_iter(ReferenceCellType::Quadrilateral)
71 .take(cell_count_owned)
72 ) {
73 assert_eq!(cell.global_index(), cell_global_count);
74 }
75
76 // Get the global indices
77 let global_vertices = mesh
78 .local_mesh()
79 .entity_iter(ReferenceCellType::Point)
80 .filter(|e| matches!(e.ownership(), Ownership::Owned))
81 .map(|e| e.global_index())
82 .collect::<Vec<_>>();
83
84 let nvertices = global_vertices.len();
85
86 let global_cells = mesh
87 .local_mesh()
88 .entity_iter(ReferenceCellType::Quadrilateral)
89 .filter(|e| matches!(e.ownership(), Ownership::Owned))
90 .map(|e| e.global_index())
91 .collect::<Vec<_>>();
92
93 let ncells = global_cells.len();
94
95 let mut total_cells: usize = 0;
96 let mut total_vertices: usize = 0;
97
98 comm.all_reduce_into(&ncells, &mut total_cells, SystemOperation::sum());
99 comm.all_reduce_into(&nvertices, &mut total_vertices, SystemOperation::sum());
100
101 // Check that the total number of cells and vertices are correct
102 assert_eq!(total_cells, (n - 1) * (n - 1));
103 assert_eq!(total_vertices, n * n);
104}Trait Implementations§
Source§impl<T: Scalar> Builder for SingleElementMeshBuilder<T>
impl<T: Scalar> Builder for SingleElementMeshBuilder<T>
Source§type Mesh = SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>
type Mesh = SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>
The type of the mesh that the builder creates
Source§type EntityDescriptor = ReferenceCellType
type EntityDescriptor = ReferenceCellType
Type used as identifier of different entity types
Source§fn add_cell_from_nodes_and_type(
&mut self,
id: usize,
nodes: &[usize],
cell_type: ReferenceCellType,
cell_degree: usize,
)
fn add_cell_from_nodes_and_type( &mut self, id: usize, nodes: &[usize], cell_type: ReferenceCellType, cell_degree: usize, )
Add a cell to the mesh
Source§fn create_mesh(&self) -> SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>
fn create_mesh(&self) -> SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>
Create the mesh
Source§fn point_count(&self) -> usize
fn point_count(&self) -> usize
Number of points
Source§fn cell_count(&self) -> usize
fn cell_count(&self) -> usize
Number of cells
Source§fn point_indices_to_ids(&self) -> &[usize]
fn point_indices_to_ids(&self) -> &[usize]
Get the insertion ids of each point
Source§fn cell_indices_to_ids(&self) -> &[usize]
fn cell_indices_to_ids(&self) -> &[usize]
Get the insertion ids of each cell
Source§fn cell_points(&self, index: usize) -> &[usize]
fn cell_points(&self, index: usize) -> &[usize]
Get the indices of the points of a cell
Source§fn cell_vertices(&self, index: usize) -> &[usize]
fn cell_vertices(&self, index: usize) -> &[usize]
Get the indices of the points of a cell
Source§fn cell_degree(&self, _index: usize) -> usize
fn cell_degree(&self, _index: usize) -> usize
Get the degree of a cell’s geometry
Source§fn npts(&self, _cell_type: Self::EntityDescriptor, _degree: usize) -> usize
fn npts(&self, _cell_type: Self::EntityDescriptor, _degree: usize) -> usize
Number of points in a cell with the given type and degree
Auto Trait Implementations§
impl<T> Freeze for SingleElementMeshBuilder<T>
impl<T> RefUnwindSafe for SingleElementMeshBuilder<T>where
T: RefUnwindSafe,
impl<T> Send for SingleElementMeshBuilder<T>
impl<T> Sync for SingleElementMeshBuilder<T>
impl<T> Unpin for SingleElementMeshBuilder<T>where
T: Unpin,
impl<T> UnsafeUnpin for SingleElementMeshBuilder<T>
impl<T> UnwindSafe for SingleElementMeshBuilder<T>where
T: UnwindSafe,
Blanket Implementations§
§impl<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
impl<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
§fn approx_from(src: Src) -> Result<Src, <Src as ApproxFrom<Src, Scheme>>::Err>
fn approx_from(src: Src) -> Result<Src, <Src as ApproxFrom<Src, Scheme>>::Err>
Convert the given value into an approximately equivalent representation.
§impl<Dst, Src, Scheme> ApproxInto<Dst, Scheme> for Srcwhere
Dst: ApproxFrom<Src, Scheme>,
Scheme: ApproxScheme,
impl<Dst, Src, Scheme> ApproxInto<Dst, Scheme> for Srcwhere
Dst: ApproxFrom<Src, Scheme>,
Scheme: ApproxScheme,
§fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>
fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>
Convert the subject into an approximately equivalent representation.
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T, Dst> ConvAsUtil<Dst> for T
impl<T, Dst> ConvAsUtil<Dst> for T
§impl<T> ConvUtil for T
impl<T> ConvUtil for T
§fn approx_as<Dst>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst>,
fn approx_as<Dst>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst>,
Approximate the subject to a given type with the default scheme.
§fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst, Scheme>,
Scheme: ApproxScheme,
fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst, Scheme>,
Scheme: ApproxScheme,
Approximate the subject to a given type with a specific scheme.
Source§impl<T, B> GmshImport for B
impl<T, B> GmshImport for B
Source§fn import_from_gmsh_v1(&mut self, s: String)
fn import_from_gmsh_v1(&mut self, s: String)
Generate mesh from a Gmsh v1 string
Source§fn import_from_gmsh_string_v2(&mut self, s: String)
fn import_from_gmsh_string_v2(&mut self, s: String)
Generate mesh from a Gmsh v2 string
Source§fn import_from_gmsh_binary_v2(
&mut self,
reader: BufReader<File>,
data_size: usize,
is_le: bool,
)
fn import_from_gmsh_binary_v2( &mut self, reader: BufReader<File>, data_size: usize, is_le: bool, )
Generate mesh from a Gmsh v2 binary
Source§fn import_from_gmsh_string_v4(&mut self, s: String)
fn import_from_gmsh_string_v4(&mut self, s: String)
Generate mesh from a Gmsh v4 string
Source§fn import_from_gmsh_binary_v4(
&mut self,
reader: BufReader<File>,
data_size: usize,
is_le: bool,
)
fn import_from_gmsh_binary_v4( &mut self, reader: BufReader<File>, data_size: usize, is_le: bool, )
Generate mesh from a Gmsh v4 binary
Source§fn import_from_gmsh(&mut self, filename: &str)
fn import_from_gmsh(&mut self, filename: &str)
Generate mesh from Gmsh
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.§impl<Src> TryFrom<Src> for Src
impl<Src> TryFrom<Src> for Src
§impl<Src, Dst> TryInto<Dst> for Srcwhere
Dst: TryFrom<Src>,
impl<Src, Dst> TryInto<Dst> for Srcwhere
Dst: TryFrom<Src>,
§impl<Src> ValueFrom<Src> for Src
impl<Src> ValueFrom<Src> for Src
§fn value_from(src: Src) -> Result<Src, <Src as ValueFrom<Src>>::Err>
fn value_from(src: Src) -> Result<Src, <Src as ValueFrom<Src>>::Err>
Convert the given value into an exactly equivalent representation.
§impl<Src, Dst> ValueInto<Dst> for Srcwhere
Dst: ValueFrom<Src>,
impl<Src, Dst> ValueInto<Dst> for Srcwhere
Dst: ValueFrom<Src>,
§fn value_into(self) -> Result<Dst, <Src as ValueInto<Dst>>::Err>
fn value_into(self) -> Result<Dst, <Src as ValueInto<Dst>>::Err>
Convert the subject into an exactly equivalent representation.