10#include "DirichletBC.h"
13#include "FunctionSpace.h"
17#include <basix/mdspan.hpp>
19#include <dolfinx/common/IndexMap.h>
20#include <dolfinx/mesh/Geometry.h>
21#include <dolfinx/mesh/Mesh.h>
22#include <dolfinx/mesh/Topology.h>
28namespace dolfinx::fem::impl
32using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
34 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
76 std::span<T> b, mdspan2_t x_dofmap,
77 std::span<
const scalar_value_type_t<T>> x, FEkernel<T>
auto kernel,
78 std::span<const std::int32_t> cells,
79 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap0,
80 fem::DofTransformKernel<T>
auto P0,
81 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap1,
82 fem::DofTransformKernel<T>
auto P1T, std::span<const T> constants,
83 std::span<const T> coeffs,
int cstride,
84 std::span<const std::uint32_t> cell_info0,
85 std::span<const std::uint32_t> cell_info1, std::span<const T> bc_values1,
86 std::span<const std::int8_t> bc_markers1, std::span<const T> x0, T scale)
91 const auto [dmap0, bs0, cells0] = dofmap0;
92 const auto [dmap1, bs1, cells1] = dofmap1;
93 assert(_bs0 < 0 or _bs0 == bs0);
94 assert(_bs1 < 0 or _bs1 == bs1);
97 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
98 std::vector<T> Ae, be;
99 assert(cells0.size() ==
cells.size());
100 assert(cells1.size() ==
cells.size());
101 for (std::size_t index = 0; index <
cells.size(); ++index)
105 std::int32_t c =
cells[index];
106 std::int32_t c0 = cells0[index];
107 std::int32_t c1 = cells1[index];
110 auto dofs1 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
111 dmap1, c1, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
115 for (std::size_t j = 0; j < dofs1.size(); ++j)
117 if constexpr (_bs1 > 0)
119 for (
int k = 0; k < _bs1; ++k)
121 assert(_bs1 * dofs1[j] + k < (
int)bc_markers1.size());
122 if (bc_markers1[_bs1 * dofs1[j] + k])
131 for (
int k = 0; k < bs1; ++k)
133 assert(bs1 * dofs1[j] + k < (
int)bc_markers1.size());
134 if (bc_markers1[bs1 * dofs1[j] + k])
147 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
148 x_dofmap, c, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
149 for (std::size_t i = 0; i < x_dofs.size(); ++i)
151 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
152 std::next(coordinate_dofs.begin(), 3 * i));
156 auto dofs0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
157 dmap0, c0, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
159 const int num_rows = bs0 * dofs0.size();
160 const int num_cols = bs1 * dofs1.size();
162 const T* coeff_array = coeffs.data() + index * cstride;
163 Ae.resize(num_rows * num_cols);
164 std::fill(Ae.begin(), Ae.end(), 0);
165 kernel(Ae.data(), coeff_array, constants.data(), coordinate_dofs.data(),
167 P0(Ae, cell_info0, c0, num_cols);
168 P1T(Ae, cell_info1, c1, num_rows);
172 std::fill(be.begin(), be.end(), 0);
173 for (std::size_t j = 0; j < dofs1.size(); ++j)
175 if constexpr (_bs1 > 0)
177 for (
int k = 0; k < _bs1; ++k)
179 const std::int32_t jj = _bs1 * dofs1[j] + k;
180 assert(jj < (
int)bc_markers1.size());
183 const T bc = bc_values1[jj];
184 const T _x0 = x0.empty() ? 0 : x0[jj];
187 for (
int m = 0; m < num_rows; ++m)
188 be[m] -= Ae[m * num_cols + _bs1 * j + k] * scale * (bc - _x0);
194 for (
int k = 0; k < bs1; ++k)
196 const std::int32_t jj = bs1 * dofs1[j] + k;
197 assert(jj < (
int)bc_markers1.size());
200 const T bc = bc_values1[jj];
201 const T _x0 = x0.empty() ? 0 : x0[jj];
203 for (
int m = 0; m < num_rows; ++m)
204 be[m] -= Ae[m * num_cols + bs1 * j + k] * scale * (bc - _x0);
210 for (std::size_t i = 0; i < dofs0.size(); ++i)
212 if constexpr (_bs0 > 0)
214 for (
int k = 0; k < _bs0; ++k)
215 b[_bs0 * dofs0[i] + k] += be[_bs0 * i + k];
219 for (
int k = 0; k < bs0; ++k)
220 b[bs0 * dofs0[i] + k] += be[bs0 * i + k];
258void _lift_bc_exterior_facets(
259 std::span<T> b, mdspan2_t x_dofmap,
260 std::span<
const scalar_value_type_t<T>> x, FEkernel<T>
auto kernel,
261 std::span<const std::int32_t> facets,
262 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap0,
263 fem::DofTransformKernel<T>
auto P0,
264 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap1,
265 fem::DofTransformKernel<T>
auto P1T, std::span<const T> constants,
266 std::span<const T> coeffs,
int cstride,
267 std::span<const std::uint32_t> cell_info0,
268 std::span<const std::uint32_t> cell_info1, std::span<const T> bc_values1,
269 std::span<const std::int8_t> bc_markers1, std::span<const T> x0, T scale)
274 const auto [dmap0, bs0, facets0] = dofmap0;
275 const auto [dmap1, bs1, facets1] = dofmap1;
278 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
279 std::vector<T> Ae, be;
280 assert(facets.size() % 2 == 0);
281 assert(facets0.size() == facets.size());
282 assert(facets1.size() == facets.size());
283 for (std::size_t index = 0; index < facets.size(); index += 2)
286 std::int32_t
cell = facets[index];
288 std::int32_t cell0 = facets0[index];
290 std::int32_t cell1 = facets1[index];
293 std::int32_t local_facet = facets[index + 1];
296 auto dofs1 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
297 dmap1, cell1, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
301 for (std::size_t j = 0; j < dofs1.size(); ++j)
303 for (
int k = 0; k < bs1; ++k)
305 if (bc_markers1[bs1 * dofs1[j] + k])
317 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
318 x_dofmap,
cell, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
319 for (std::size_t i = 0; i < x_dofs.size(); ++i)
321 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
322 std::next(coordinate_dofs.begin(), 3 * i));
326 auto dofs0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
327 dmap0, cell0, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
329 const int num_rows = bs0 * dofs0.size();
330 const int num_cols = bs1 * dofs1.size();
332 const T* coeff_array = coeffs.data() + index / 2 * cstride;
333 Ae.resize(num_rows * num_cols);
334 std::fill(Ae.begin(), Ae.end(), 0);
335 kernel(Ae.data(), coeff_array, constants.data(), coordinate_dofs.data(),
336 &local_facet,
nullptr);
337 P0(Ae, cell_info0, cell0, num_cols);
338 P1T(Ae, cell_info1, cell1, num_rows);
342 std::fill(be.begin(), be.end(), 0);
343 for (std::size_t j = 0; j < dofs1.size(); ++j)
345 for (
int k = 0; k < bs1; ++k)
347 const std::int32_t jj = bs1 * dofs1[j] + k;
350 const T bc = bc_values1[jj];
351 const T _x0 = x0.empty() ? 0 : x0[jj];
353 for (
int m = 0; m < num_rows; ++m)
354 be[m] -= Ae[m * num_cols + bs1 * j + k] * scale * (bc - _x0);
359 for (std::size_t i = 0; i < dofs0.size(); ++i)
360 for (
int k = 0; k < bs0; ++k)
361 b[bs0 * dofs0[i] + k] += be[bs0 * i + k];
399void _lift_bc_interior_facets(
400 std::span<T> b, mdspan2_t x_dofmap,
401 std::span<
const scalar_value_type_t<T>> x,
int num_cell_facets,
402 FEkernel<T>
auto kernel, std::span<const std::int32_t> facets,
403 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap0,
404 fem::DofTransformKernel<T>
auto P0,
405 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap1,
406 fem::DofTransformKernel<T>
auto P1T, std::span<const T> constants,
407 std::span<const T> coeffs,
int cstride,
408 std::span<const std::uint32_t> cell_info0,
409 std::span<const std::uint32_t> cell_info1,
410 const std::function<std::uint8_t(std::size_t)>& get_perm,
411 std::span<const T> bc_values1, std::span<const std::int8_t> bc_markers1,
412 std::span<const T> x0, T scale)
417 const auto [dmap0, bs0, facets0] = dofmap0;
418 const auto [dmap1, bs1, facets1] = dofmap1;
421 using X = scalar_value_type_t<T>;
422 std::vector<X> coordinate_dofs(2 * x_dofmap.extent(1) * 3);
423 std::span<X> cdofs0(coordinate_dofs.data(), x_dofmap.extent(1) * 3);
424 std::span<X> cdofs1(coordinate_dofs.data() + x_dofmap.extent(1) * 3,
425 x_dofmap.extent(1) * 3);
426 std::vector<T> Ae, be;
429 std::vector<std::int32_t> dmapjoint0, dmapjoint1;
430 assert(facets.size() % 4 == 0);
432 const int num_dofs0 = dmap0.extent(1);
433 const int num_dofs1 = dmap1.extent(1);
434 assert(facets0.size() == facets.size());
435 assert(facets1.size() == facets.size());
436 for (std::size_t index = 0; index < facets.size(); index += 4)
440 std::array
cells{facets[index], facets[index + 2]};
441 std::array cells0{facets0[index], facets0[index + 2]};
442 std::array cells1{facets1[index], facets1[index + 2]};
445 std::array<std::int32_t, 2> local_facet
446 = {facets[index + 1], facets[index + 3]};
449 auto x_dofs0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
450 x_dofmap, cells[0], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
451 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
453 std::copy_n(std::next(x.begin(), 3 * x_dofs0[i]), 3,
454 std::next(cdofs0.begin(), 3 * i));
456 auto x_dofs1 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
457 x_dofmap, cells[1], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
458 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
460 std::copy_n(std::next(x.begin(), 3 * x_dofs1[i]), 3,
461 std::next(cdofs1.begin(), 3 * i));
466 = std::span(dmap0.data_handle() + cells0[0] * num_dofs0, num_dofs0);
468 = std::span(dmap0.data_handle() + cells0[1] * num_dofs0, num_dofs0);
470 dmapjoint0.resize(dmap0_cell0.size() + dmap0_cell1.size());
471 std::copy(dmap0_cell0.begin(), dmap0_cell0.end(), dmapjoint0.begin());
472 std::copy(dmap0_cell1.begin(), dmap0_cell1.end(),
473 std::next(dmapjoint0.begin(), dmap0_cell0.size()));
476 = std::span(dmap1.data_handle() + cells1[0] * num_dofs1, num_dofs1);
478 = std::span(dmap1.data_handle() + cells1[1] * num_dofs1, num_dofs1);
480 dmapjoint1.resize(dmap1_cell0.size() + dmap1_cell1.size());
481 std::copy(dmap1_cell0.begin(), dmap1_cell0.end(), dmapjoint1.begin());
482 std::copy(dmap1_cell1.begin(), dmap1_cell1.end(),
483 std::next(dmapjoint1.begin(), dmap1_cell0.size()));
487 for (std::size_t j = 0; j < dmap1_cell0.size(); ++j)
489 for (
int k = 0; k < bs1; ++k)
491 if (bc_markers1[bs1 * dmap1_cell0[j] + k])
500 for (std::size_t j = 0; j < dmap1_cell1.size(); ++j)
502 for (
int k = 0; k < bs1; ++k)
504 if (bc_markers1[bs1 * dmap1_cell1[j] + k])
515 const int num_rows = bs0 * dmapjoint0.size();
516 const int num_cols = bs1 * dmapjoint1.size();
519 Ae.resize(num_rows * num_cols);
520 std::fill(Ae.begin(), Ae.end(), 0);
521 const std::array perm{
522 get_perm(cells[0] * num_cell_facets + local_facet[0]),
523 get_perm(cells[1] * num_cell_facets + local_facet[1])};
524 kernel(Ae.data(), coeffs.data() + index / 2 * cstride, constants.data(),
525 coordinate_dofs.data(), local_facet.data(), perm.data());
527 std::span<T> _Ae(Ae);
528 std::span<T> sub_Ae0 = _Ae.subspan(bs0 * dmap0_cell0.size() * num_cols,
529 bs0 * dmap0_cell1.size() * num_cols);
531 P0(_Ae, cell_info0, cells0[0], num_cols);
532 P0(sub_Ae0, cell_info0, cells0[1], num_cols);
533 P1T(_Ae, cell_info1, cells1[0], num_rows);
535 for (
int row = 0; row < num_rows; ++row)
539 std::span<T> sub_Ae1 = _Ae.subspan(
540 row * num_cols + bs1 * dmap1_cell0.size(), bs1 * dmap1_cell1.size());
541 P1T(sub_Ae1, cell_info1, cells1[1], 1);
545 std::fill(be.begin(), be.end(), 0);
548 for (std::size_t j = 0; j < dmap1_cell0.size(); ++j)
550 for (
int k = 0; k < bs1; ++k)
552 const std::int32_t jj = bs1 * dmap1_cell0[j] + k;
555 const T bc = bc_values1[jj];
556 const T _x0 = x0.empty() ? 0 : x0[jj];
558 for (
int m = 0; m < num_rows; ++m)
559 be[m] -= Ae[m * num_cols + bs1 * j + k] * scale * (bc - _x0);
565 const int offset = bs1 * dmap1_cell0.size();
566 for (std::size_t j = 0; j < dmap1_cell1.size(); ++j)
568 for (
int k = 0; k < bs1; ++k)
570 const std::int32_t jj = bs1 * dmap1_cell1[j] + k;
573 const T bc = bc_values1[jj];
574 const T _x0 = x0.empty() ? 0 : x0[jj];
576 for (
int m = 0; m < num_rows; ++m)
579 -= Ae[m * num_cols + offset + bs1 * j + k] * scale * (bc - _x0);
585 for (std::size_t i = 0; i < dmap0_cell0.size(); ++i)
586 for (
int k = 0; k < bs0; ++k)
587 b[bs0 * dmap0_cell0[i] + k] += be[bs0 * i + k];
589 const int offset_be = bs0 * dmap0_cell0.size();
590 for (std::size_t i = 0; i < dmap0_cell1.size(); ++i)
591 for (
int k = 0; k < bs0; ++k)
592 b[bs0 * dmap0_cell1[i] + k] += be[offset_be + bs0 * i + k];
620 fem::DofTransformKernel<T>
auto P0, std::span<T> b, mdspan2_t x_dofmap,
621 std::span<
const scalar_value_type_t<T>> x,
622 std::span<const std::int32_t> cells,
623 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap,
624 FEkernel<T>
auto kernel, std::span<const T> constants,
625 std::span<const T> coeffs,
int cstride,
626 std::span<const std::uint32_t> cell_info0)
631 const auto [dmap, bs, cells0] = dofmap;
632 assert(_bs < 0 or _bs == bs);
635 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
636 std::vector<T> be(bs * dmap.extent(1));
637 std::span<T> _be(be);
640 for (std::size_t index = 0; index <
cells.size(); ++index)
643 std::int32_t c =
cells[index];
644 std::int32_t c0 = cells0[index];
647 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
648 x_dofmap, c, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
649 for (std::size_t i = 0; i < x_dofs.size(); ++i)
651 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
652 std::next(coordinate_dofs.begin(), 3 * i));
656 std::fill(be.begin(), be.end(), 0);
657 kernel(be.data(), coeffs.data() + index * cstride, constants.data(),
658 coordinate_dofs.data(),
nullptr,
nullptr);
659 P0(_be, cell_info0, c0, 1);
662 auto dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
663 dmap, c0, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
664 if constexpr (_bs > 0)
666 for (std::size_t i = 0; i < dofs.size(); ++i)
667 for (
int k = 0; k < _bs; ++k)
668 b[_bs * dofs[i] + k] += be[_bs * i + k];
672 for (std::size_t i = 0; i < dofs.size(); ++i)
673 for (
int k = 0; k < bs; ++k)
674 b[bs * dofs[i] + k] += be[bs * i + k];
702void assemble_exterior_facets(
703 fem::DofTransformKernel<T>
auto P0, std::span<T> b, mdspan2_t x_dofmap,
704 std::span<
const scalar_value_type_t<T>> x,
705 std::span<const std::int32_t> facets,
706 std::tuple<mdspan2_t,
int, std::span<const std::int32_t>> dofmap,
707 FEkernel<T>
auto fn, std::span<const T> constants,
708 std::span<const T> coeffs,
int cstride,
709 std::span<const std::uint32_t> cell_info0)
714 const auto [dmap, bs, facets0] = dofmap;
715 assert(_bs < 0 or _bs == bs);
719 const int num_dofs = dmap.extent(1);
720 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
721 std::vector<T> be(bs * num_dofs);
722 std::span<T> _be(be);
723 assert(facets.size() % 2 == 0);
724 assert(facets0.size() == facets.size());
725 for (std::size_t index = 0; index < facets.size(); index += 2)
729 std::int32_t
cell = facets[index];
730 std::int32_t local_facet = facets[index + 1];
731 std::int32_t cell0 = facets0[index];
734 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
735 x_dofmap,
cell, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
736 for (std::size_t i = 0; i < x_dofs.size(); ++i)
738 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
739 std::next(coordinate_dofs.begin(), 3 * i));
743 std::fill(be.begin(), be.end(), 0);
744 fn(be.data(), coeffs.data() + index / 2 * cstride, constants.data(),
745 coordinate_dofs.data(), &local_facet,
nullptr);
747 P0(_be, cell_info0, cell0, 1);
750 auto dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
751 dmap, cell0, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
752 if constexpr (_bs > 0)
754 for (std::size_t i = 0; i < dofs.size(); ++i)
755 for (
int k = 0; k < _bs; ++k)
756 b[_bs * dofs[i] + k] += be[_bs * i + k];
760 for (std::size_t i = 0; i < dofs.size(); ++i)
761 for (
int k = 0; k < bs; ++k)
762 b[bs * dofs[i] + k] += be[bs * i + k];
792void assemble_interior_facets(
793 fem::DofTransformKernel<T>
auto P0, std::span<T> b, mdspan2_t x_dofmap,
794 std::span<
const scalar_value_type_t<T>> x,
int num_cell_facets,
795 std::span<const std::int32_t> facets,
796 std::tuple<
const DofMap&,
int, std::span<const std::int32_t>> dofmap,
797 FEkernel<T>
auto fn, std::span<const T> constants,
798 std::span<const T> coeffs,
int cstride,
799 std::span<const std::uint32_t> cell_info0,
800 const std::function<std::uint8_t(std::size_t)>& get_perm)
805 const auto [dmap, bs, facets0] = dofmap;
806 assert(_bs < 0 or _bs == bs);
809 using X = scalar_value_type_t<T>;
810 std::vector<X> coordinate_dofs(2 * x_dofmap.extent(1) * 3);
811 std::span<X> cdofs0(coordinate_dofs.data(), x_dofmap.extent(1) * 3);
812 std::span<X> cdofs1(coordinate_dofs.data() + x_dofmap.extent(1) * 3,
813 x_dofmap.extent(1) * 3);
816 assert(facets.size() % 4 == 0);
817 assert(facets0.size() == facets.size());
818 for (std::size_t index = 0; index < facets.size(); index += 4)
821 std::array<std::int32_t, 2>
cells{facets[index], facets[index + 2]};
822 std::array<std::int32_t, 2> cells0{facets0[index], facets0[index + 2]};
825 std::array<std::int32_t, 2> local_facet{facets[index + 1],
829 auto x_dofs0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
830 x_dofmap, cells[0], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
831 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
833 std::copy_n(std::next(x.begin(), 3 * x_dofs0[i]), 3,
834 std::next(cdofs0.begin(), 3 * i));
836 auto x_dofs1 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
837 x_dofmap, cells[1], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
838 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
840 std::copy_n(std::next(x.begin(), 3 * x_dofs1[i]), 3,
841 std::next(cdofs1.begin(), 3 * i));
845 std::span<const std::int32_t> dmap0 = dmap.cell_dofs(cells0[0]);
846 std::span<const std::int32_t> dmap1 = dmap.cell_dofs(cells0[1]);
849 be.resize(bs * (dmap0.size() + dmap1.size()));
850 std::fill(be.begin(), be.end(), 0);
851 const std::array perm{
852 get_perm(cells[0] * num_cell_facets + local_facet[0]),
853 get_perm(cells[1] * num_cell_facets + local_facet[1])};
854 fn(be.data(), coeffs.data() + index / 2 * cstride, constants.data(),
855 coordinate_dofs.data(), local_facet.data(), perm.data());
857 std::span<T> _be(be);
858 std::span<T> sub_be = _be.subspan(bs * dmap0.size(), bs * dmap1.size());
860 P0(be, cell_info0, cells0[0], 1);
861 P0(sub_be, cell_info0, cells0[1], 1);
864 if constexpr (_bs > 0)
866 for (std::size_t i = 0; i < dmap0.size(); ++i)
867 for (
int k = 0; k < _bs; ++k)
868 b[_bs * dmap0[i] + k] += be[_bs * i + k];
869 for (std::size_t i = 0; i < dmap1.size(); ++i)
870 for (
int k = 0; k < _bs; ++k)
871 b[_bs * dmap1[i] + k] += be[_bs * (i + dmap0.size()) + k];
875 for (std::size_t i = 0; i < dmap0.size(); ++i)
876 for (
int k = 0; k < bs; ++k)
877 b[bs * dmap0[i] + k] += be[bs * i + k];
878 for (std::size_t i = 0; i < dmap1.size(); ++i)
879 for (
int k = 0; k < bs; ++k)
880 b[bs * dmap1[i] + k] += be[bs * (i + dmap0.size()) + k];
901template <dolfinx::scalar T, std::
floating_po
int U>
902void lift_bc(std::span<T> b,
const Form<T, U>& a, mdspan2_t x_dofmap,
903 std::span<
const scalar_value_type_t<T>> x,
904 std::span<const T> constants,
905 const std::map<std::pair<IntegralType, int>,
906 std::pair<std::span<const T>,
int>>& coefficients,
907 std::span<const T> bc_values1,
908 std::span<const std::int8_t> bc_markers1, std::span<const T> x0,
912 std::shared_ptr<const mesh::Mesh<U>> mesh = a.mesh();
915 auto mesh0 = a.function_spaces().at(0)->mesh();
918 auto mesh1 = a.function_spaces().at(1)->mesh();
922 assert(a.function_spaces().at(0));
923 assert(a.function_spaces().at(1));
924 auto dofmap0 = a.function_spaces()[0]->dofmap()->map();
925 const int bs0 = a.function_spaces()[0]->dofmap()->bs();
926 auto element0 = a.function_spaces()[0]->element();
927 auto dofmap1 = a.function_spaces()[1]->dofmap()->map();
928 const int bs1 = a.function_spaces()[1]->dofmap()->bs();
929 auto element1 = a.function_spaces()[1]->element();
932 std::span<const std::uint32_t> cell_info0;
933 std::span<const std::uint32_t> cell_info1;
935 if (element0->needs_dof_transformations()
936 or element1->needs_dof_transformations() or a.needs_facet_permutations())
938 mesh0->topology_mutable()->create_entity_permutations();
939 mesh1->topology_mutable()->create_entity_permutations();
940 cell_info0 = std::span(mesh0->topology()->get_cell_permutation_info());
941 cell_info1 = std::span(mesh1->topology()->get_cell_permutation_info());
944 fem::DofTransformKernel<T>
auto P0
946 fem::DofTransformKernel<T>
auto P1T
947 = element1->template dof_transformation_right_fn<T>(
956 if (bs0 == 1 and bs1 == 1)
958 _lift_bc_cells<T, 1, 1>(
959 b, x_dofmap, x, kernel, cells,
962 constants, coeffs, cstride, cell_info0, cell_info1, bc_values1,
963 bc_markers1, x0, scale);
965 else if (bs0 == 3 and bs1 == 3)
967 _lift_bc_cells<T, 3, 3>(
968 b, x_dofmap, x, kernel, cells,
971 constants, coeffs, cstride, cell_info0, cell_info1, bc_values1,
972 bc_markers1, x0, scale);
976 _lift_bc_cells(b, x_dofmap, x, kernel, cells,
980 P1T, constants, coeffs, cstride, cell_info0, cell_info1,
981 bc_values1, bc_markers1, x0, scale);
989 auto& [coeffs, cstride]
991 _lift_bc_exterior_facets(
993 {dofmap0, bs0, a.domain(IntegralType::exterior_facet, i, *mesh0)}, P0,
994 {dofmap1, bs1, a.domain(IntegralType::exterior_facet, i, *mesh1)}, P1T,
995 constants, coeffs, cstride, cell_info0, cell_info1, bc_values1,
996 bc_markers1, x0, scale);
1001 std::function<std::uint8_t(std::size_t)> get_perm;
1002 if (a.needs_facet_permutations())
1004 mesh->topology_mutable()->create_entity_permutations();
1005 const std::vector<std::uint8_t>& perms
1006 = mesh->topology()->get_facet_permutations();
1007 get_perm = [&perms](std::size_t i) {
return perms[i]; };
1010 get_perm = [](std::size_t) {
return 0; };
1019 auto& [coeffs, cstride]
1021 _lift_bc_interior_facets(
1022 b, x_dofmap, x, num_cell_facets, kernel,
1024 {dofmap0, bs0, a.domain(IntegralType::interior_facet, i, *mesh0)}, P0,
1025 {dofmap1, bs1, a.domain(IntegralType::interior_facet, i, *mesh1)},
1026 P1T, constants, coeffs, cstride, cell_info0, cell_info1, get_perm,
1027 bc_values1, bc_markers1, x0, scale);
1053template <dolfinx::scalar T, std::
floating_po
int U>
1055 std::span<T> b,
const std::vector<std::shared_ptr<
const Form<T, U>>> a,
1056 mdspan2_t x_dofmap, std::span<
const scalar_value_type_t<T>> x,
1057 const std::vector<std::span<const T>>& constants,
1058 const std::vector<std::map<std::pair<IntegralType, int>,
1059 std::pair<std::span<const T>,
int>>>& coeffs,
1060 const std::vector<std::vector<std::shared_ptr<
const DirichletBC<T, U>>>>&
1062 const std::vector<std::span<const T>>& x0, T scale)
1065 if (!x0.empty() and x0.size() != a.size())
1067 throw std::runtime_error(
1068 "Mismatch in size between x0 and bilinear form in assembler.");
1071 if (a.size() != bcs1.size())
1073 throw std::runtime_error(
1074 "Mismatch in size between a and bcs in assembler.");
1077 for (std::size_t j = 0; j < a.size(); ++j)
1079 std::vector<std::int8_t> bc_markers1;
1080 std::vector<T> bc_values1;
1081 if (a[j] and !bcs1[j].empty())
1083 assert(a[j]->function_spaces().at(0));
1085 auto V1 = a[j]->function_spaces()[1];
1087 auto map1 = V1->dofmap()->index_map;
1088 const int bs1 = V1->dofmap()->index_map_bs();
1090 const int crange = bs1 * (map1->size_local() + map1->num_ghosts());
1091 bc_markers1.assign(crange,
false);
1092 bc_values1.assign(crange, 0);
1093 for (
const std::shared_ptr<
const DirichletBC<T, U>>& bc : bcs1[j])
1095 bc->mark_dofs(bc_markers1);
1096 bc->dof_values(bc_values1);
1101 lift_bc<T>(b, *a[j], x_dofmap, x, constants[j], coeffs[j], bc_values1,
1102 bc_markers1, x0[j], scale);
1106 lift_bc<T>(b, *a[j], x_dofmap, x, constants[j], coeffs[j], bc_values1,
1107 bc_markers1, std::span<const T>(), scale);
1121template <dolfinx::scalar T, std::
floating_po
int U>
1122void assemble_vector(
1123 std::span<T> b,
const Form<T, U>& L, mdspan2_t x_dofmap,
1124 std::span<
const scalar_value_type_t<T>> x, std::span<const T> constants,
1125 const std::map<std::pair<IntegralType, int>,
1126 std::pair<std::span<const T>,
int>>& coefficients)
1129 std::shared_ptr<const mesh::Mesh<U>> mesh = L.mesh();
1133 auto mesh0 = L.function_spaces().at(0)->mesh();
1137 assert(L.function_spaces().at(0));
1138 auto element = L.function_spaces().at(0)->element();
1140 std::shared_ptr<const fem::DofMap> dofmap
1141 = L.function_spaces().at(0)->dofmap();
1143 auto dofs = dofmap->map();
1144 const int bs = dofmap->bs();
1146 fem::DofTransformKernel<T>
auto P0
1149 std::span<const std::uint32_t> cell_info0;
1150 if (element->needs_dof_transformations() or L.needs_facet_permutations())
1152 mesh0->topology_mutable()->create_entity_permutations();
1153 cell_info0 = std::span(mesh0->topology()->get_cell_permutation_info());
1164 impl::assemble_cells<T, 1>(
1165 P0, b, x_dofmap, x, cells,
1167 coeffs, cstride, cell_info0);
1171 impl::assemble_cells<T, 3>(
1172 P0, b, x_dofmap, x, cells,
1174 coeffs, cstride, cell_info0);
1178 impl::assemble_cells(P0, b, x_dofmap, x, cells,
1180 fn, constants, coeffs, cstride, cell_info0);
1188 auto& [coeffs, cstride]
1190 std::span<const std::int32_t> facets
1194 impl::assemble_exterior_facets<T, 1>(
1195 P0, b, x_dofmap, x, facets,
1197 constants, coeffs, cstride, cell_info0);
1201 impl::assemble_exterior_facets<T, 3>(
1202 P0, b, x_dofmap, x, facets,
1204 constants, coeffs, cstride, cell_info0);
1208 impl::assemble_exterior_facets(
1209 P0, b, x_dofmap, x, facets,
1211 constants, coeffs, cstride, cell_info0);
1217 std::function<std::uint8_t(std::size_t)> get_perm;
1218 if (L.needs_facet_permutations())
1220 mesh->topology_mutable()->create_entity_permutations();
1221 const std::vector<std::uint8_t>& perms
1222 = mesh->topology()->get_facet_permutations();
1223 get_perm = [&perms](std::size_t i) {
return perms[i]; };
1226 get_perm = [](std::size_t) {
return 0; };
1235 auto& [coeffs, cstride]
1237 std::span<const std::int32_t> facets
1241 impl::assemble_interior_facets<T, 1>(
1242 P0, b, x_dofmap, x, num_cell_facets, facets,
1244 fn, constants, coeffs, cstride, cell_info0, get_perm);
1248 impl::assemble_interior_facets<T, 3>(
1249 P0, b, x_dofmap, x, num_cell_facets, facets,
1251 fn, constants, coeffs, cstride, cell_info0, get_perm);
1255 impl::assemble_interior_facets(
1256 P0, b, x_dofmap, x, num_cell_facets, facets,
1258 fn, constants, coeffs, cstride, cell_info0, get_perm);
1270template <dolfinx::scalar T, std::
floating_po
int U>
1271void assemble_vector(
1272 std::span<T> b,
const Form<T, U>& L, std::span<const T> constants,
1273 const std::map<std::pair<IntegralType, int>,
1274 std::pair<std::span<const T>,
int>>& coefficients)
1276 std::shared_ptr<const mesh::Mesh<U>> mesh = L.mesh();
1278 if constexpr (std::is_same_v<U, scalar_value_type_t<T>>)
1279 assemble_vector(b, L, mesh->geometry().dofmap(), mesh->geometry().x(),
1280 constants, coefficients);
1283 auto x = mesh->geometry().x();
1284 std::vector<scalar_value_type_t<T>> _x(x.begin(), x.end());
1285 assemble_vector(b, L, mesh->geometry().dofmap(), _x, constants,
Degree-of-freedom map representations and tools.
Functions supporting finite element method operations.
void cells(la::SparsityPattern &pattern, std::array< std::span< const std::int32_t >, 2 > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:15
IntegralType
Type of integral.
Definition Form.h:34
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
int cell_num_entities(CellType type, int dim)
Definition cell_types.cpp:139
CellType
Cell type identifier.
Definition cell_types.h:22