10#include "cell_types.h"
34template <std::
floating_po
int T>
35Mesh<T> build_tri(MPI_Comm comm,
const std::array<std::array<double, 2>, 2>& p,
36 std::array<std::size_t, 2> n,
40template <std::
floating_po
int T>
41Mesh<T> build_quad(MPI_Comm comm,
const std::array<std::array<double, 2>, 2> p,
42 std::array<std::size_t, 2> n,
45template <std::
floating_po
int T>
46std::vector<T> create_geom(MPI_Comm comm,
47 const std::array<std::array<double, 3>, 2>& p,
48 std::array<std::size_t, 3> n);
50template <std::
floating_po
int T>
51Mesh<T> build_tet(MPI_Comm comm,
const std::array<std::array<double, 3>, 2>& p,
52 std::array<std::size_t, 3> n,
55template <std::
floating_po
int T>
56Mesh<T> build_hex(MPI_Comm comm,
const std::array<std::array<double, 3>, 2>& p,
57 std::array<std::size_t, 3> n,
60template <std::
floating_po
int T>
61Mesh<T> build_prism(MPI_Comm comm,
62 const std::array<std::array<double, 3>, 2>& p,
63 std::array<std::size_t, 3> n,
84template <std::
floating_po
int T =
double>
86 std::array<std::size_t, 3> n,
CellType celltype,
94 case CellType::tetrahedron:
95 return impl::build_tet<T>(comm, p, n, partitioner);
96 case CellType::hexahedron:
97 return impl::build_hex<T>(comm, p, n, partitioner);
99 return impl::build_prism<T>(comm, p, n, partitioner);
101 throw std::runtime_error(
"Generate box mesh. Wrong cell type");
121template <std::
floating_po
int T =
double>
123 const std::array<std::array<double, 2>, 2>& p,
124 std::array<std::size_t, 2> n,
CellType celltype,
130 case CellType::triangle:
131 return impl::build_tri<T>(comm, p, n, partitioner, diagonal);
132 case CellType::quadrilateral:
133 return impl::build_quad<T>(comm, p, n, partitioner);
135 throw std::runtime_error(
"Generate rectangle mesh. Wrong cell type");
153template <std::
floating_po
int T =
double>
155 const std::array<std::array<double, 2>, 2>& p,
156 std::array<std::size_t, 2> n,
CellType celltype,
159 return create_rectangle<T>(comm, p, n, celltype,
nullptr, diagonal);
174template <std::
floating_po
int T =
double>
187 const T ab = (b - a) /
static_cast<T
>(nx);
189 if (std::abs(a - b) < DBL_EPSILON)
191 throw std::runtime_error(
192 "Length of interval is zero. Check your dimensions.");
197 throw std::runtime_error(
198 "Interval length is negative. Check order of arguments.");
202 throw std::runtime_error(
203 "Number of points on interval must be at least 1");
206 std::vector<T> geom(nx + 1);
207 for (std::size_t ix = 0; ix <= nx; ix++)
208 geom[ix] = a + ab *
static_cast<T
>(ix);
211 std::vector<std::int64_t> cells(nx * 2);
212 for (std::size_t ix = 0; ix < nx; ++ix)
213 for (std::size_t j = 0; j < 2; ++j)
214 cells[2 * ix + j] = ix + j;
217 {element}, geom, {geom.size(), 1}, partitioner);
223 {element}, std::vector<T>(), {0, 1}, partitioner);
229template <std::
floating_po
int T>
230std::vector<T> create_geom(MPI_Comm comm,
231 const std::array<std::array<double, 3>, 2>& p,
232 std::array<std::size_t, 3> n)
235 const std::array<double, 3> p0 = p[0];
236 const std::array<double, 3> p1 = p[1];
237 std::int64_t nx = n[0];
238 std::int64_t ny = n[1];
239 std::int64_t nz = n[2];
241 const std::int64_t n_points = (nx + 1) * (ny + 1) * (nz + 1);
246 const double x0 = std::min(p0[0], p1[0]);
247 const double x1 = std::max(p0[0], p1[0]);
248 const double y0 = std::min(p0[1], p1[1]);
249 const double y1 = std::max(p0[1], p1[1]);
250 const double z0 = std::min(p0[2], p1[2]);
251 const double z1 = std::max(p0[2], p1[2]);
255 const T ab = (b - a) /
static_cast<T
>(nx);
258 const T cd = (d - c) /
static_cast<T
>(ny);
261 const T ef = (f - e) /
static_cast<T
>(nz);
263 if (std::abs(x0 - x1) < 2.0 * DBL_EPSILON
264 or std::abs(y0 - y1) < 2.0 * DBL_EPSILON
265 or std::abs(z0 - z1) < 2.0 * DBL_EPSILON)
267 throw std::runtime_error(
268 "Box seems to have zero width, height or depth. Check dimensions");
271 if (nx < 1 || ny < 1 || nz < 1)
273 throw std::runtime_error(
274 "BoxMesh has non-positive number of vertices in some dimension");
277 std::vector<T> geom((range_p[1] - range_p[0]) * 3);
278 const std::int64_t sqxy = (nx + 1) * (ny + 1);
279 std::array<T, 3> point;
280 for (std::int64_t v = range_p[0]; v < range_p[1]; ++v)
282 const std::int64_t iz = v / sqxy;
283 const std::int64_t p = v % sqxy;
284 const std::int64_t iy = p / (nx + 1);
285 const std::int64_t ix = p % (nx + 1);
286 const T z = e + ef *
static_cast<T
>(iz);
287 const T y = c + cd *
static_cast<T
>(iy);
288 const T x = a + ab *
static_cast<T
>(ix);
290 for (std::size_t i = 0; i < 3; i++)
291 geom[3 * (v - range_p[0]) + i] = point[i];
297template <std::
floating_po
int T>
298Mesh<T> build_tet(MPI_Comm comm,
const std::array<std::array<double, 3>, 2>& p,
299 std::array<std::size_t, 3> n,
302 common::Timer timer(
"Build BoxMesh");
304 std::vector geom = create_geom<T>(comm, p, n);
306 const std::int64_t nx = n[0];
307 const std::int64_t ny = n[1];
308 const std::int64_t nz = n[2];
309 const std::int64_t n_cells = nx * ny * nz;
312 const std::size_t cell_range = range_c[1] - range_c[0];
313 std::vector<std::int64_t>
cells(6 * cell_range * 4);
316 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
318 const int iz = i / (nx * ny);
319 const int j = i % (nx * ny);
320 const int iy = j / nx;
321 const int ix = j % nx;
323 const std::int64_t v0 = iz * (nx + 1) * (ny + 1) + iy * (nx + 1) + ix;
324 const std::int64_t v1 = v0 + 1;
325 const std::int64_t v2 = v0 + (nx + 1);
326 const std::int64_t v3 = v1 + (nx + 1);
327 const std::int64_t v4 = v0 + (nx + 1) * (ny + 1);
328 const std::int64_t v5 = v1 + (nx + 1) * (ny + 1);
329 const std::int64_t v6 = v2 + (nx + 1) * (ny + 1);
330 const std::int64_t v7 = v3 + (nx + 1) * (ny + 1);
333 std::array<std::int64_t, 24> c
334 = {v0, v1, v3, v7, v0, v1, v7, v5, v0, v5, v7, v4,
335 v0, v3, v2, v7, v0, v6, v4, v7, v0, v2, v6, v7};
336 std::size_t offset = 6 * (i - range_c[0]);
337 std::copy(c.begin(), c.end(), std::next(
cells.begin(), 4 * offset));
340 fem::CoordinateElement<T> element(CellType::tetrahedron, 1);
342 {element}, geom, {geom.size() / 3, 3}, partitioner);
345template <std::
floating_po
int T>
346mesh::Mesh<T> build_hex(MPI_Comm comm,
347 const std::array<std::array<double, 3>, 2>& p,
348 std::array<std::size_t, 3> n,
351 std::vector geom = create_geom<T>(comm, p, n);
353 const std::int64_t nx = n[0];
354 const std::int64_t ny = n[1];
355 const std::int64_t nz = n[2];
356 const std::int64_t n_cells = nx * ny * nz;
359 const std::size_t cell_range = range_c[1] - range_c[0];
360 std::vector<std::int64_t>
cells(cell_range * 8);
363 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
365 const std::int64_t iz = i / (nx * ny);
366 const std::int64_t j = i % (nx * ny);
367 const std::int64_t iy = j / nx;
368 const std::int64_t ix = j % nx;
370 const std::int64_t v0 = (iz * (ny + 1) + iy) * (nx + 1) + ix;
371 const std::int64_t v1 = v0 + 1;
372 const std::int64_t v2 = v0 + (nx + 1);
373 const std::int64_t v3 = v1 + (nx + 1);
374 const std::int64_t v4 = v0 + (nx + 1) * (ny + 1);
375 const std::int64_t v5 = v1 + (nx + 1) * (ny + 1);
376 const std::int64_t v6 = v2 + (nx + 1) * (ny + 1);
377 const std::int64_t v7 = v3 + (nx + 1) * (ny + 1);
379 std::array<std::int64_t, 8> c = {v0, v1, v2, v3, v4, v5, v6, v7};
380 std::copy(c.begin(), c.end(),
381 std::next(
cells.begin(), (i - range_c[0]) * 8));
384 fem::CoordinateElement<T> element(CellType::hexahedron, 1);
386 {element}, geom, {geom.size() / 3, 3}, partitioner);
389template <std::
floating_po
int T>
390Mesh<T> build_prism(MPI_Comm comm,
391 const std::array<std::array<double, 3>, 2>& p,
392 std::array<std::size_t, 3> n,
395 std::vector geom = create_geom<T>(comm, p, n);
397 const std::int64_t nx = n[0];
398 const std::int64_t ny = n[1];
399 const std::int64_t nz = n[2];
400 const std::int64_t n_cells = nx * ny * nz;
403 const std::size_t cell_range = range_c[1] - range_c[0];
404 std::vector<std::int64_t>
cells(2 * cell_range * 6);
407 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
409 const std::int64_t iz = i / (nx * ny);
410 const std::int64_t j = i % (nx * ny);
411 const std::int64_t iy = j / nx;
412 const std::int64_t ix = j % nx;
414 const std::int64_t v0 = (iz * (ny + 1) + iy) * (nx + 1) + ix;
415 const std::int64_t v1 = v0 + 1;
416 const std::int64_t v2 = v0 + (nx + 1);
417 const std::int64_t v3 = v1 + (nx + 1);
418 const std::int64_t v4 = v0 + (nx + 1) * (ny + 1);
419 const std::int64_t v5 = v1 + (nx + 1) * (ny + 1);
420 const std::int64_t v6 = v2 + (nx + 1) * (ny + 1);
421 const std::int64_t v7 = v3 + (nx + 1) * (ny + 1);
423 std::array<std::int64_t, 6> c0 = {v0, v1, v2, v4, v5, v6};
424 std::array<std::int64_t, 6> c1 = {v1, v2, v3, v5, v6, v7};
426 std::copy(c0.begin(), c0.end(),
427 std::next(
cells.begin(), 6 * ((i - range_c[0]) * 2)));
428 std::copy(c1.begin(), c1.end(),
429 std::next(
cells.begin(), 6 * ((i - range_c[0]) * 2 + 1)));
432 fem::CoordinateElement<T> element(CellType::prism, 1);
434 {element}, geom, {geom.size() / 3, 3}, partitioner);
437template <std::
floating_po
int T>
438Mesh<T> build_tri(MPI_Comm comm,
const std::array<std::array<double, 2>, 2>& p,
439 std::array<std::size_t, 2> n,
443 fem::CoordinateElement<T> element(CellType::triangle, 1);
450 {element}, std::vector<T>(), {0, 2}, partitioner);
453 const std::array<double, 2> p0 = p[0];
454 const std::array<double, 2> p1 = p[1];
456 const std::size_t nx = n[0];
457 const std::size_t ny = n[1];
460 const T x0 = std::min(p0[0], p1[0]);
461 const T x1 = std::max(p0[0], p1[0]);
462 const T y0 = std::min(p0[1], p1[1]);
463 const T y1 = std::max(p0[1], p1[1]);
467 const T ab = (b - a) /
static_cast<T
>(nx);
470 const T cd = (d - c) /
static_cast<T
>(ny);
472 if (std::abs(x0 - x1) < DBL_EPSILON || std::abs(y0 - y1) < DBL_EPSILON)
474 throw std::runtime_error(
"Rectangle seems to have zero width, height or "
475 "depth. Check dimensions");
478 if (nx < 1 or ny < 1)
480 throw std::runtime_error(
481 "Rectangle has non-positive number of vertices in some dimension: "
482 "number of vertices must be at least 1 in each dimension");
489 case DiagonalType::crossed:
490 nv = (nx + 1) * (ny + 1) + nx * ny;
494 nv = (nx + 1) * (ny + 1);
498 std::vector<T> geom(nv * 2);
499 std::vector<std::int64_t>
cells(nc * 3);
503 for (std::size_t iy = 0; iy <= ny; iy++)
505 const T x1 = c + cd *
static_cast<T
>(iy);
506 for (std::size_t ix = 0; ix <= nx; ix++)
508 geom[2 *
vertex + 0] = a + ab *
static_cast<T
>(ix);
509 geom[2 *
vertex + 1] = x1;
517 case DiagonalType::crossed:
518 for (std::size_t iy = 0; iy < ny; iy++)
520 const T x1 = c + cd * (
static_cast<T
>(iy) + 0.5);
521 for (std::size_t ix = 0; ix < nx; ix++)
523 geom[2 *
vertex + 0] = a + ab * (
static_cast<T
>(ix) + 0.5);
524 geom[2 *
vertex + 1] = x1;
536 case DiagonalType::crossed:
538 for (std::size_t iy = 0; iy < ny; iy++)
540 for (std::size_t ix = 0; ix < nx; ix++)
542 const std::size_t v0 = iy * (nx + 1) + ix;
543 const std::size_t v1 = v0 + 1;
544 const std::size_t v2 = v0 + (nx + 1);
545 const std::size_t v3 = v1 + (nx + 1);
546 const std::size_t vmid = (nx + 1) * (ny + 1) + iy * nx + ix;
549 std::array<std::size_t, 12> c
550 = {v0, v1, vmid, v0, v2, vmid, v1, v3, vmid, v2, v3, vmid};
551 std::size_t offset = iy * nx + ix;
552 std::copy(c.begin(), c.end(), std::next(
cells.begin(), 4 * offset * 3));
560 for (std::size_t iy = 0; iy < ny; iy++)
565 case DiagonalType::right_left:
567 local_diagonal = DiagonalType::right;
569 local_diagonal = DiagonalType::left;
571 case DiagonalType::left_right:
573 local_diagonal = DiagonalType::left;
575 local_diagonal = DiagonalType::right;
580 for (std::size_t ix = 0; ix < nx; ix++)
582 const std::size_t v0 = iy * (nx + 1) + ix;
583 const std::size_t v1 = v0 + 1;
584 const std::size_t v2 = v0 + (nx + 1);
585 const std::size_t v3 = v1 + (nx + 1);
587 std::size_t offset = iy * nx + ix;
588 switch (local_diagonal)
590 case DiagonalType::left:
592 std::array<std::size_t, 6> c = {v0, v1, v2, v1, v2, v3};
593 std::copy(c.begin(), c.end(),
594 std::next(
cells.begin(), 2 * offset * 3));
595 if (diagonal == DiagonalType::right_left
596 or diagonal == DiagonalType::left_right)
598 local_diagonal = DiagonalType::right;
604 std::array<std::size_t, 6> c = {v0, v1, v3, v0, v2, v3};
605 std::copy(c.begin(), c.end(),
606 std::next(
cells.begin(), 2 * offset * 3));
607 if (diagonal == DiagonalType::right_left
608 or diagonal == DiagonalType::left_right)
610 local_diagonal = DiagonalType::left;
620 {element}, geom, {geom.size() / 2, 2}, partitioner);
623template <std::
floating_po
int T>
624Mesh<T> build_quad(MPI_Comm comm,
const std::array<std::array<double, 2>, 2> p,
625 std::array<std::size_t, 2> n,
628 fem::CoordinateElement<T> element(CellType::quadrilateral, 1);
635 {element}, std::vector<T>(), {0, 2}, partitioner);
638 const std::size_t nx = n[0];
639 const std::size_t ny = n[1];
643 const T ab = (b - a) /
static_cast<T
>(nx);
647 const T cd = (d - c) /
static_cast<T
>(ny);
650 std::vector<T> geom((nx + 1) * (ny + 1) * 2);
652 for (std::size_t ix = 0; ix <= nx; ix++)
654 T x0 = a + ab *
static_cast<T
>(ix);
655 for (std::size_t iy = 0; iy <= ny; iy++)
657 geom[2 *
vertex + 0] = x0;
658 geom[2 *
vertex + 1] = c + cd *
static_cast<T
>(iy);
664 std::vector<std::int64_t>
cells(nx * ny * 4);
665 for (std::size_t ix = 0; ix < nx; ix++)
667 for (std::size_t iy = 0; iy < ny; iy++)
669 const std::size_t i0 = ix * (ny + 1);
670 std::size_t
cell = ix * ny + iy;
671 std::array<std::size_t, 4> c
672 = {i0 + iy, i0 + iy + 1, i0 + iy + ny + 1, i0 + iy + ny + 2};
673 std::copy(c.begin(), c.end(), std::next(
cells.begin(), 4 * cell));
678 {element}, geom, {geom.size() / 2, 2}, partitioner);
A CoordinateElement manages coordinate mappings for isoparametric cells.
Definition CoordinateElement.h:39
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
int size(MPI_Comm comm)
Return size of the group (number of processes) associated with the communicator.
Definition MPI.cpp:72
int rank(MPI_Comm comm)
Return process rank for the communicator.
Definition MPI.cpp:64
constexpr std::array< std::int64_t, 2 > local_range(int rank, std::int64_t N, int size)
Return local range for the calling process, partitioning the global [0, N - 1] range across all ranks...
Definition MPI.h:91
void cells(la::SparsityPattern &pattern, std::span< const std::int32_t > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:18
AdjacencyList< typename std::decay_t< U >::value_type > regular_adjacency_list(U &&data, int degree)
Construct a constant degree (valency) adjacency list.
Definition AdjacencyList.h:183
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
Mesh< T > create_box(MPI_Comm comm, const std::array< std::array< double, 3 >, 2 > &p, std::array< std::size_t, 3 > n, CellType celltype, mesh::CellPartitionFunction partitioner=nullptr)
Create a uniform mesh::Mesh over rectangular prism spanned by the two points p.
Definition generation.h:85
std::function< graph::AdjacencyList< std::int32_t >(MPI_Comm comm, int nparts, int tdim, const graph::AdjacencyList< std::int64_t > &cells)> CellPartitionFunction
Signature for the cell partitioning function. The function should compute the destination rank for ce...
Definition utils.h:195
DiagonalType
Enum for different diagonal types.
Definition generation.h:23
Mesh< T > create_rectangle(MPI_Comm comm, const std::array< std::array< double, 2 >, 2 > &p, std::array< std::size_t, 2 > n, CellType celltype, const CellPartitionFunction &partitioner, DiagonalType diagonal=DiagonalType::right)
Create a uniform mesh::Mesh over the rectangle spanned by the two points p.
Definition generation.h:122
Mesh< typename std::remove_reference_t< typename U::value_type > > create_mesh(MPI_Comm comm, const graph::AdjacencyList< std::int64_t > &cells, const std::vector< fem::CoordinateElement< typename std::remove_reference_t< typename U::value_type > > > &elements, const U &x, std::array< std::size_t, 2 > xshape, CellPartitionFunction partitioner)
Create a mesh using a provided mesh partitioning function.
Definition utils.h:780
Mesh< T > create_interval(MPI_Comm comm, std::size_t nx, std::array< double, 2 > x, CellPartitionFunction partitioner=nullptr)
Interval mesh of the 1D line [a, b].
Definition generation.h:175
CellType
Cell type identifier.
Definition cell_types.h:22
CellPartitionFunction create_cell_partitioner(mesh::GhostMode ghost_mode=mesh::GhostMode::none, const graph::partition_fn &partfn=&graph::partition_graph)
Create a function that computes destination rank for mesh cells in this rank by applying the default ...
Definition utils.cpp:84