32  static_assert(std::is_same_v<typename Container::value_type, T>);
 
   41  static_assert(std::is_same_v<value_type, typename container_type::value_type>,
 
   42                "Scalar type and container value type must be the same.");
 
   47  Vector(std::shared_ptr<const common::IndexMap> map, 
int bs)
 
   48      : _map(map), _scatterer(std::make_shared<common::Scatterer<>>(*_map, 
bs)),
 
   49        _bs(
bs), _buffer_local(_scatterer->local_buffer_size()),
 
   50        _buffer_remote(_scatterer->remote_buffer_size()),
 
   51        _x(
bs * (map->size_local() + map->num_ghosts()))
 
 
   57      : _map(x._map), _scatterer(x._scatterer), _bs(x._bs),
 
   58        _request(1, MPI_REQUEST_NULL), _buffer_local(x._buffer_local),
 
   59        _buffer_remote(x._buffer_remote), _x(x._x)
 
 
   65      : _map(std::move(x._map)), _scatterer(std::move(x._scatterer)),
 
   66        _bs(std::move(x._bs)),
 
   67        _request(std::exchange(x._request, {MPI_REQUEST_NULL})),
 
   68        _buffer_local(std::move(x._buffer_local)),
 
   69        _buffer_remote(std::move(x._buffer_remote)), _x(std::move(x._x))
 
 
   87    const std::int32_t local_size = _bs * _map->size_local();
 
   88    std::span<const value_type> x_local(_x.data(), local_size);
 
   90    auto pack = [](
auto&& in, 
auto&& idx, 
auto&& out)
 
   92      for (std::size_t i = 0; i < idx.size(); ++i)
 
   95    pack(x_local, _scatterer->local_indices(), _buffer_local);
 
   97    _scatterer->scatter_fwd_begin(std::span<const value_type>(_buffer_local),
 
   98                                  std::span<value_type>(_buffer_remote),
 
   99                                  std::span<MPI_Request>(_request));
 
 
  106    const std::int32_t local_size = _bs * _map->size_local();
 
  107    const std::int32_t num_ghosts = _bs * _map->num_ghosts();
 
  108    std::span<value_type> x_remote(_x.data() + local_size, num_ghosts);
 
  109    _scatterer->scatter_fwd_end(std::span<MPI_Request>(_request));
 
  111    auto unpack = [](
auto&& in, 
auto&& idx, 
auto&& out, 
auto op)
 
  113      for (std::size_t i = 0; i < idx.size(); ++i)
 
  114        out[idx[i]] = op(out[idx[i]], in[i]);
 
  117    unpack(_buffer_remote, _scatterer->remote_indices(), x_remote,
 
  118           [](
auto , 
auto b) { return b; });
 
 
  133    const std::int32_t local_size = _bs * _map->size_local();
 
  134    const std::int32_t num_ghosts = _bs * _map->num_ghosts();
 
  135    std::span<value_type> x_remote(_x.data() + local_size, num_ghosts);
 
  137    auto pack = [](
auto&& in, 
auto&& idx, 
auto&& out)
 
  139      for (std::size_t i = 0; i < idx.size(); ++i)
 
  142    pack(x_remote, _scatterer->remote_indices(), _buffer_remote);
 
  144    _scatterer->scatter_rev_begin(std::span<const value_type>(_buffer_remote),
 
  145                                  std::span<value_type>(_buffer_local),
 
 
  155  template <
class BinaryOperation>
 
  158    const std::int32_t local_size = _bs * _map->size_local();
 
  159    std::span<value_type> x_local(_x.data(), local_size);
 
  160    _scatterer->scatter_rev_end(_request);
 
  162    auto unpack = [](
auto&& in, 
auto&& idx, 
auto&& out, 
auto op)
 
  164      for (std::size_t i = 0; i < idx.size(); ++i)
 
  165        out[idx[i]] = op(out[idx[i]], in[i]);
 
  167    unpack(_buffer_local, _scatterer->local_indices(), x_local, op);
 
 
  175  template <
class BinaryOperation>
 
  183  std::shared_ptr<const common::IndexMap> 
index_map()
 const { 
return _map; }
 
  186  constexpr int bs()
 const { 
return _bs; }
 
  189  std::span<const value_type> 
array()
 const 
  191    return std::span<const value_type>(_x);
 
 
  199  std::shared_ptr<const common::IndexMap> _map;
 
  202  std::shared_ptr<const common::Scatterer<>> _scatterer;
 
  208  std::vector<MPI_Request> _request = {MPI_REQUEST_NULL};
 
 
  226  using T = 
typename V::value_type;
 
  227  const std::int32_t local_size = a.bs() * a.index_map()->size_local();
 
  228  if (local_size != b.bs() * b.index_map()->size_local())
 
  229    throw std::runtime_error(
"Incompatible vector sizes");
 
  230  std::span<const T> x_a = a.array().subspan(0, local_size);
 
  231  std::span<const T> x_b = b.array().subspan(0, local_size);
 
  233  const T local = std::transform_reduce(
 
  234      x_a.begin(), x_a.end(), x_b.begin(), 
static_cast<T
>(0), std::plus{},
 
  237        if constexpr (std::is_same<T, std::complex<double>>::value
 
  238                      or std::is_same<T, std::complex<float>>::value)
 
  240          return std::conj(a) * b;
 
  247  MPI_Allreduce(&local, &result, 1, dolfinx::MPI::mpi_type<T>(), MPI_SUM,
 
  248                a.index_map()->comm());
 
 
  269  using T = 
typename V::value_type;
 
  274    std::int32_t size_local = x.bs() * x.index_map()->size_local();
 
  275    std::span<const T> data = x.array().subspan(0, size_local);
 
  276    using U = 
typename dolfinx::scalar_value_type_t<T>;
 
  278        = std::accumulate(data.begin(), data.end(), U(0),
 
  279                          [](
auto norm, 
auto x) { 
return norm + std::abs(x); });
 
  281    MPI_Allreduce(&local_l1, &l1, 1, MPI::mpi_type<U>(), MPI_SUM,
 
  282                  x.index_map()->comm());
 
  289    std::int32_t size_local = x.bs() * x.index_map()->size_local();
 
  290    std::span<const T> data = x.array().subspan(0, size_local);
 
  291    auto max_pos = std::max_element(data.begin(), data.end(), [](T a, T b)
 
  292                                    { return std::norm(a) < std::norm(b); });
 
  293    auto local_linf = std::abs(*max_pos);
 
  294    decltype(local_linf) linf = 0;
 
  295    MPI_Allreduce(&local_linf, &linf, 1, MPI::mpi_type<
decltype(linf)>(),
 
  296                  MPI_MAX, x.index_map()->comm());
 
  300    throw std::runtime_error(
"Norm type not supported");
 
 
  312  using T = 
typename V::value_type;
 
  313  using U = 
typename dolfinx::scalar_value_type_t<T>;
 
  316  for (std::size_t i = 0; i < basis.size(); ++i)
 
  320    V& bi = basis[i].get();
 
  321    for (std::size_t j = 0; j < i; ++j)
 
  323      const V& bj = basis[j].get();
 
  327      std::transform(bj.array().begin(), bj.array().end(), bi.array().begin(),
 
  328                     bi.mutable_array().begin(),
 
  329                     [dot_ij](
auto xj, 
auto xi) { return xi - dot_ij * xj; });
 
  333    auto norm = la::norm(bi, la::Norm::l2);
 
  334    if (
norm * 
norm < std::numeric_limits<U>::epsilon())
 
  336      throw std::runtime_error(
 
  337          "Linear dependency detected. Cannot orthogonalize.");
 
  339    std::transform(bi.array().begin(), bi.array().end(),
 
  340                   bi.mutable_array().begin(),
 
  341                   [
norm](
auto x) { return x / norm; });
 
 
  351  using T = 
typename V::value_type;
 
  352  using U = 
typename dolfinx::scalar_value_type_t<T>;
 
  355  for (std::size_t i = 0; i < basis.size(); i++)
 
  357    for (std::size_t j = i; j < basis.size(); j++)
 
  359      T delta_ij = (i == j) ? T(1) : T(0);
 
  361      if (std::norm(delta_ij - dot_ij) > std::numeric_limits<U>::epsilon())