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