Skip to main content

SingleElementMeshBuilder

Struct SingleElementMeshBuilder 

Source
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>

Source

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
Hide additional 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}
Source

pub fn new_with_capacity( gdim: usize, npoints: usize, ncells: usize, data: (ReferenceCellType, usize), ) -> Self

Create a new mesh builder with capacaty for a given number of points and cells

Trait Implementations§

Source§

impl<T: Scalar> Builder for SingleElementMeshBuilder<T>

Source§

type Mesh = SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>

The type of the mesh that the builder creates
Source§

type T = T

The floating point type used for coordinates
Source§

type CellData<'a> = &'a [usize]

The type of the data that is input to add a cell
Source§

type EntityDescriptor = ReferenceCellType

Type used as identifier of different entity types
Source§

fn add_point(&mut self, id: usize, data: &[T])

Add a point to the mesh
Source§

fn add_cell(&mut self, id: usize, cell_data: &[usize])

Add a cell to the mesh
Source§

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>>

Create the mesh
Source§

fn point_count(&self) -> usize

Number of points
Source§

fn cell_count(&self) -> usize

Number of cells
Source§

fn point_indices_to_ids(&self) -> &[usize]

Get the insertion ids of each point
Source§

fn cell_indices_to_ids(&self) -> &[usize]

Get the insertion ids of each cell
Source§

fn cell_points(&self, index: usize) -> &[usize]

Get the indices of the points of a cell
Source§

fn cell_vertices(&self, index: usize) -> &[usize]

Get the indices of the points of a cell
Source§

fn point(&self, index: usize) -> &[T]

Get the coordinates of a point
Source§

fn points(&self) -> &[T]

Get all points
Source§

fn cell_type(&self, _index: usize) -> ReferenceCellType

Get the type of a cell
Source§

fn cell_degree(&self, _index: usize) -> usize

Get the degree of a cell’s geometry
Source§

fn gdim(&self) -> usize

Geometric dimension
Source§

fn tdim(&self) -> usize

Topoligical dimension
Source§

fn npts(&self, _cell_type: Self::EntityDescriptor, _degree: usize) -> usize

Number of points in a cell with the given type and degree
Source§

fn add_point_parametric_coords( &mut self, id: usize, entity_dim: usize, coords: &[T], )

Add parametric coordinates for a point (optional)
Source§

fn point_parametric_coords(&self, index: usize) -> Option<(usize, &[T])>

Get parametric coordinates for a point, if available
Source§

impl<T: Debug + Scalar> Debug for SingleElementMeshBuilder<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<Src, Scheme> ApproxFrom<Src, Scheme> for Src
where Scheme: ApproxScheme,

§

type Err = NoError

The error type produced by a failed conversion.
§

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 Src
where Dst: ApproxFrom<Src, Scheme>, Scheme: ApproxScheme,

§

type Err = <Dst as ApproxFrom<Src, Scheme>>::Err

The error type produced by a failed conversion.
§

fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>

Convert the subject into an approximately equivalent representation.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, Dst> ConvAsUtil<Dst> for T

§

fn approx(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst>,

Approximate the subject with the default scheme.
§

fn approx_by<Scheme>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst, Scheme>, Scheme: ApproxScheme,

Approximate the subject with a specific scheme.
§

impl<T> ConvUtil for T

§

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,

Approximate the subject to a given type with a specific scheme.
§

fn into_as<Dst>(self) -> Dst
where Self: Sized + Into<Dst>,

Convert the subject to a given type.
§

fn try_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + TryInto<Dst>,

Attempt to convert the subject to a given type.
§

fn value_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + ValueInto<Dst>,

Attempt a value conversion of the subject to a given type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, B> GmshImport for B
where T: FromStr + FromBytes + Debug, <T as FromBytes>::Bytes: Sized, B: Builder<T = T, EntityDescriptor = ReferenceCellType>,

Source§

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)

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, )

Generate mesh from a Gmsh v2 binary
Source§

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, )

Generate mesh from a Gmsh v4 binary
Source§

fn import_from_gmsh(&mut self, filename: &str)

Generate mesh from Gmsh
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

§

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

Checks if self is actually part of its subset T (and can be converted to it).
§

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

The inclusion map: converts self to the equivalent element of its superset.
§

impl<Src> TryFrom<Src> for Src

§

type Err = NoError

The error type produced by a failed conversion.
§

fn try_from(src: Src) -> Result<Src, <Src as TryFrom<Src>>::Err>

Convert the given value into the subject type.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<Src, Dst> TryInto<Dst> for Src
where Dst: TryFrom<Src>,

§

type Err = <Dst as TryFrom<Src>>::Err

The error type produced by a failed conversion.
§

fn try_into(self) -> Result<Dst, <Src as TryInto<Dst>>::Err>

Convert the subject into the destination type.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<Src> ValueFrom<Src> for Src

§

type Err = NoError

The error type produced by a failed conversion.
§

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 Src
where Dst: ValueFrom<Src>,

§

type Err = <Dst as ValueFrom<Src>>::Err

The error type produced by a failed conversion.
§

fn value_into(self) -> Result<Dst, <Src as ValueInto<Dst>>::Err>

Convert the subject into an exactly equivalent representation.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T, U> Imply<T> for U