Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/d6/d6c/generation_8h_source.html
DOLFINx 0.7.3
DOLFINx C++ interface
Loading...
Searching...
No Matches
generation.h
1// Copyright (C) 2005-2017 Anders Logg and Garth N. Wells
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Mesh.h"
10#include "cell_types.h"
11#include "utils.h"
12#include <array>
13#include <cfloat>
14#include <concepts>
15#include <cstddef>
16#include <mpi.h>
17
18namespace dolfinx::mesh
19{
20
22enum class DiagonalType
23{
24 left,
25 right,
26 crossed,
27 shared_facet,
28 left_right,
29 right_left
30};
31
32namespace impl
33{
34template <std::floating_point 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,
37 const CellPartitionFunction& partitioner,
38 DiagonalType diagonal);
39
40template <std::floating_point 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,
43 const CellPartitionFunction& partitioner);
44
45template <std::floating_point 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);
49
50template <std::floating_point 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,
53 const CellPartitionFunction& partitioner);
54
55template <std::floating_point 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,
58 const CellPartitionFunction& partitioner);
59
60template <std::floating_point 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,
64 const CellPartitionFunction& partitioner);
65
66} // namespace impl
67
84template <std::floating_point T = double>
85Mesh<T> create_box(MPI_Comm comm, const std::array<std::array<double, 3>, 2>& p,
86 std::array<std::size_t, 3> n, CellType celltype,
87 mesh::CellPartitionFunction partitioner = nullptr)
88{
89 if (!partitioner and dolfinx::MPI::size(comm) > 1)
90 partitioner = create_cell_partitioner();
91
92 switch (celltype)
93 {
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);
98 case CellType::prism:
99 return impl::build_prism<T>(comm, p, n, partitioner);
100 default:
101 throw std::runtime_error("Generate box mesh. Wrong cell type");
102 }
103}
104
121template <std::floating_point T = double>
123 const std::array<std::array<double, 2>, 2>& p,
124 std::array<std::size_t, 2> n, CellType celltype,
125 const CellPartitionFunction& partitioner,
126 DiagonalType diagonal = DiagonalType::right)
127{
128 switch (celltype)
129 {
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);
134 default:
135 throw std::runtime_error("Generate rectangle mesh. Wrong cell type");
136 }
137}
138
153template <std::floating_point T = double>
155 const std::array<std::array<double, 2>, 2>& p,
156 std::array<std::size_t, 2> n, CellType celltype,
157 DiagonalType diagonal = DiagonalType::right)
158{
159 return create_rectangle<T>(comm, p, n, celltype, nullptr, diagonal);
160}
161
174template <std::floating_point T = double>
175Mesh<T> create_interval(MPI_Comm comm, std::size_t nx, std::array<double, 2> x,
176 CellPartitionFunction partitioner = nullptr)
177{
178 if (!partitioner and dolfinx::MPI::size(comm) > 1)
179 partitioner = create_cell_partitioner();
180
181 fem::CoordinateElement<T> element(CellType::interval, 1);
182
183 if (dolfinx::MPI::rank(comm) == 0)
184 {
185 const T a = x[0];
186 const T b = x[1];
187 const T ab = (b - a) / static_cast<T>(nx);
188
189 if (std::abs(a - b) < DBL_EPSILON)
190 {
191 throw std::runtime_error(
192 "Length of interval is zero. Check your dimensions.");
193 }
194
195 if (b < a)
196 {
197 throw std::runtime_error(
198 "Interval length is negative. Check order of arguments.");
199 }
200
201 if (nx < 1)
202 throw std::runtime_error(
203 "Number of points on interval must be at least 1");
204
205 // Create vertices
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);
209
210 // Create intervals
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;
215
216 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 2),
217 {element}, geom, {geom.size(), 1}, partitioner);
218 }
219 else
220 {
221 return create_mesh(
222 comm, graph::regular_adjacency_list(std::vector<std::int64_t>(), 2),
223 {element}, std::vector<T>(), {0, 1}, partitioner);
224 }
225}
226
227namespace impl
228{
229template <std::floating_point 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)
233{
234 // Extract data
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];
240
241 const std::int64_t n_points = (nx + 1) * (ny + 1) * (nz + 1);
242 std::array range_p = dolfinx::MPI::local_range(
243 dolfinx::MPI::rank(comm), n_points, dolfinx::MPI::size(comm));
244
245 // Extract minimum and maximum coordinates
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]);
252
253 const T a = x0;
254 const T b = x1;
255 const T ab = (b - a) / static_cast<T>(nx);
256 const T c = y0;
257 const T d = y1;
258 const T cd = (d - c) / static_cast<T>(ny);
259 const T e = z0;
260 const T f = z1;
261 const T ef = (f - e) / static_cast<T>(nz);
262
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)
266 {
267 throw std::runtime_error(
268 "Box seems to have zero width, height or depth. Check dimensions");
269 }
270
271 if (nx < 1 || ny < 1 || nz < 1)
272 {
273 throw std::runtime_error(
274 "BoxMesh has non-positive number of vertices in some dimension");
275 }
276
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)
281 {
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);
289 point = {x, y, z};
290 for (std::size_t i = 0; i < 3; i++)
291 geom[3 * (v - range_p[0]) + i] = point[i];
292 }
293
294 return geom;
295}
296
297template <std::floating_point 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,
300 const CellPartitionFunction& partitioner)
301{
302 common::Timer timer("Build BoxMesh");
303
304 std::vector geom = create_geom<T>(comm, p, n);
305
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;
310 std::array range_c = dolfinx::MPI::local_range(
311 dolfinx::MPI::rank(comm), n_cells, dolfinx::MPI::size(comm));
312 const std::size_t cell_range = range_c[1] - range_c[0];
313 std::vector<std::int64_t> cells(6 * cell_range * 4);
314
315 // Create tetrahedra
316 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
317 {
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;
322
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);
331
332 // Note that v0 < v1 < v2 < v3 < vmid
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));
338 }
339
340 fem::CoordinateElement<T> element(CellType::tetrahedron, 1);
341 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 4),
342 {element}, geom, {geom.size() / 3, 3}, partitioner);
343}
344
345template <std::floating_point 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,
349 const CellPartitionFunction& partitioner)
350{
351 std::vector geom = create_geom<T>(comm, p, n);
352
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;
357 std::array range_c = dolfinx::MPI::local_range(
358 dolfinx::MPI::rank(comm), n_cells, dolfinx::MPI::size(comm));
359 const std::size_t cell_range = range_c[1] - range_c[0];
360 std::vector<std::int64_t> cells(cell_range * 8);
361
362 // Create cuboids
363 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
364 {
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;
369
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);
378
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));
382 }
383
384 fem::CoordinateElement<T> element(CellType::hexahedron, 1);
385 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 8),
386 {element}, geom, {geom.size() / 3, 3}, partitioner);
387}
388
389template <std::floating_point 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,
393 const CellPartitionFunction& partitioner)
394{
395 std::vector geom = create_geom<T>(comm, p, n);
396
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;
401 std::array range_c = dolfinx::MPI::local_range(
402 dolfinx::MPI::rank(comm), n_cells, dolfinx::MPI::size(comm));
403 const std::size_t cell_range = range_c[1] - range_c[0];
404 std::vector<std::int64_t> cells(2 * cell_range * 6);
405
406 // Create cuboids
407 for (std::int64_t i = range_c[0]; i < range_c[1]; ++i)
408 {
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;
413
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);
422
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};
425
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)));
430 }
431
432 fem::CoordinateElement<T> element(CellType::prism, 1);
433 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 6),
434 {element}, geom, {geom.size() / 3, 3}, partitioner);
435}
436
437template <std::floating_point 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,
440 const CellPartitionFunction& partitioner,
441 DiagonalType diagonal)
442{
443 fem::CoordinateElement<T> element(CellType::triangle, 1);
444
445 // Receive mesh if not rank 0
446 if (dolfinx::MPI::rank(comm) != 0)
447 {
448 return create_mesh(
449 comm, graph::regular_adjacency_list(std::vector<std::int64_t>(), 3),
450 {element}, std::vector<T>(), {0, 2}, partitioner);
451 }
452
453 const std::array<double, 2> p0 = p[0];
454 const std::array<double, 2> p1 = p[1];
455
456 const std::size_t nx = n[0];
457 const std::size_t ny = n[1];
458
459 // Extract minimum and maximum coordinates
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]);
464
465 const T a = x0;
466 const T b = x1;
467 const T ab = (b - a) / static_cast<T>(nx);
468 const T c = y0;
469 const T d = y1;
470 const T cd = (d - c) / static_cast<T>(ny);
471
472 if (std::abs(x0 - x1) < DBL_EPSILON || std::abs(y0 - y1) < DBL_EPSILON)
473 {
474 throw std::runtime_error("Rectangle seems to have zero width, height or "
475 "depth. Check dimensions");
476 }
477
478 if (nx < 1 or ny < 1)
479 {
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");
483 }
484
485 // Create vertices and cells
486 std::size_t nv, nc;
487 switch (diagonal)
488 {
489 case DiagonalType::crossed:
490 nv = (nx + 1) * (ny + 1) + nx * ny;
491 nc = 4 * nx * ny;
492 break;
493 default:
494 nv = (nx + 1) * (ny + 1);
495 nc = 2 * nx * ny;
496 }
497
498 std::vector<T> geom(nv * 2);
499 std::vector<std::int64_t> cells(nc * 3);
500
501 // Create main vertices
502 std::size_t vertex = 0;
503 for (std::size_t iy = 0; iy <= ny; iy++)
504 {
505 const T x1 = c + cd * static_cast<T>(iy);
506 for (std::size_t ix = 0; ix <= nx; ix++)
507 {
508 geom[2 * vertex + 0] = a + ab * static_cast<T>(ix);
509 geom[2 * vertex + 1] = x1;
510 ++vertex;
511 }
512 }
513
514 // Create midpoint vertices if the mesh type is crossed
515 switch (diagonal)
516 {
517 case DiagonalType::crossed:
518 for (std::size_t iy = 0; iy < ny; iy++)
519 {
520 const T x1 = c + cd * (static_cast<T>(iy) + 0.5);
521 for (std::size_t ix = 0; ix < nx; ix++)
522 {
523 geom[2 * vertex + 0] = a + ab * (static_cast<T>(ix) + 0.5);
524 geom[2 * vertex + 1] = x1;
525 ++vertex;
526 }
527 }
528 break;
529 default:
530 break;
531 }
532
533 // Create triangles
534 switch (diagonal)
535 {
536 case DiagonalType::crossed:
537 {
538 for (std::size_t iy = 0; iy < ny; iy++)
539 {
540 for (std::size_t ix = 0; ix < nx; ix++)
541 {
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;
547
548 // Note that v0 < v1 < v2 < v3 < vmid
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));
553 }
554 }
555 break;
556 }
557 default:
558 {
559 DiagonalType local_diagonal = diagonal;
560 for (std::size_t iy = 0; iy < ny; iy++)
561 {
562 // Set up alternating diagonal
563 switch (diagonal)
564 {
565 case DiagonalType::right_left:
566 if (iy % 2)
567 local_diagonal = DiagonalType::right;
568 else
569 local_diagonal = DiagonalType::left;
570 break;
571 case DiagonalType::left_right:
572 if (iy % 2)
573 local_diagonal = DiagonalType::left;
574 else
575 local_diagonal = DiagonalType::right;
576 break;
577 default:
578 break;
579 }
580 for (std::size_t ix = 0; ix < nx; ix++)
581 {
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);
586
587 std::size_t offset = iy * nx + ix;
588 switch (local_diagonal)
589 {
590 case DiagonalType::left:
591 {
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)
597 {
598 local_diagonal = DiagonalType::right;
599 }
600 break;
601 }
602 default:
603 {
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)
609 {
610 local_diagonal = DiagonalType::left;
611 }
612 }
613 }
614 }
615 }
616 }
617 }
618
619 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 3),
620 {element}, geom, {geom.size() / 2, 2}, partitioner);
621}
622
623template <std::floating_point 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,
626 const CellPartitionFunction& partitioner)
627{
628 fem::CoordinateElement<T> element(CellType::quadrilateral, 1);
629
630 // Receive mesh if not rank 0
631 if (dolfinx::MPI::rank(comm) != 0)
632 {
633 return create_mesh(
634 comm, graph::regular_adjacency_list(std::vector<std::int64_t>(), 4),
635 {element}, std::vector<T>(), {0, 2}, partitioner);
636 }
637
638 const std::size_t nx = n[0];
639 const std::size_t ny = n[1];
640
641 const T a = p[0][0];
642 const T b = p[1][0];
643 const T ab = (b - a) / static_cast<T>(nx);
644
645 const T c = p[0][1];
646 const T d = p[1][1];
647 const T cd = (d - c) / static_cast<T>(ny);
648
649 // Create vertices
650 std::vector<T> geom((nx + 1) * (ny + 1) * 2);
651 std::size_t vertex = 0;
652 for (std::size_t ix = 0; ix <= nx; ix++)
653 {
654 T x0 = a + ab * static_cast<T>(ix);
655 for (std::size_t iy = 0; iy <= ny; iy++)
656 {
657 geom[2 * vertex + 0] = x0;
658 geom[2 * vertex + 1] = c + cd * static_cast<T>(iy);
659 ++vertex;
660 }
661 }
662
663 // Create rectangles
664 std::vector<std::int64_t> cells(nx * ny * 4);
665 for (std::size_t ix = 0; ix < nx; ix++)
666 {
667 for (std::size_t iy = 0; iy < ny; iy++)
668 {
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));
674 }
675 }
676
677 return create_mesh(comm, graph::regular_adjacency_list(std::move(cells), 4),
678 {element}, geom, {geom.size() / 2, 2}, partitioner);
679}
680
681} // namespace impl
682
683} // namespace dolfinx::mesh
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