13#include <dolfinx/common/IndexMap.h>
14#include <dolfinx/common/MPI.h>
15#include <dolfinx/common/Scatterer.h>
16#include <dolfinx/common/types.h>
29template <
class F,
class Container,
class ScatterContainer>
31 f(idx.cbegin(), idx.cend(), x.cbegin(), x.begin());
35template <
class GetPtr,
class U,
class T>
37 { f(x) } -> std::same_as<T*>;
38} and
requires(GetPtr f,
const U x) {
39 { f(x) } -> std::same_as<const T*>;
50template <
typename T,
typename Container = std::vector<T>,
51 typename ScatterContainer = std::vector<std::
int32_t>>
54 static_assert(std::is_same_v<typename Container::value_type, T>);
56 template <
typename,
typename,
typename>
68 static void dispatch_bs(
int bs, F&& f)
73 return f(std::integral_constant<int, 1>{});
75 return f(std::integral_constant<int, 2>{});
77 return f(std::integral_constant<int, 3>{});
89 return [
bs = _bs](
typename ScatterContainer::const_iterator idx_first,
90 typename ScatterContainer::const_iterator idx_last,
91 const auto in_first,
auto out_first)
98 for (
auto idx = idx_first; idx != idx_last; ++idx)
100 auto in = std::next(in_first, (*idx) * B);
101 for (
int j = 0; j < B; ++j, ++in, ++out)
116 return get_unpack_op([](
auto,
auto received) {
return received; });
124 template <
typename BinaryOp>
125 auto get_unpack_op(BinaryOp op)
127 return [op,
bs = _bs](
typename ScatterContainer::const_iterator idx_first,
128 typename ScatterContainer::const_iterator idx_last,
129 const auto in_first,
auto out_first)
136 for (
auto idx = idx_first; idx != idx_last; ++idx)
138 auto out = std::next(out_first, (*idx) * B);
139 for (
int j = 0; j < B; ++j, ++in, ++out)
140 *out = op(*out, *in);
153 static_assert(std::is_same_v<value_type, typename container_type::value_type>,
154 "Scalar type and container value type must be the same.");
168 Vector(std::shared_ptr<const common::IndexMap> map,
int bs)
170 std::make_shared<
common::Scatterer<ScatterContainer>>(*map))
180 Vector(std::shared_ptr<const common::IndexMap> map,
int bs,
182 : _map(std::move(map)), _bs(
bs),
183 _x(
bs * (_map->size_local() + _map->num_ghosts())),
185 _buffer_local(
bs * _scatterer->local_indices_block().size()),
186 _buffer_remote(
bs * _scatterer->remote_indices_block().size())
210 std::shared_ptr<const common::Scatterer<ScatterContainer>>
211 scatter_ptr(
auto sc)
const
213 using SC =
typename std::remove_cv<
214 typename decltype(sc)::element_type>::type::container_type;
215 if constexpr (std::is_same_v<ScatterContainer, SC>)
218 return std::make_shared<common::Scatterer<ScatterContainer>>(*sc);
241 template <
typename T0,
typename Container0,
typename ScatterContainer0>
242 explicit Vector(
const Vector<T0, Container0, ScatterContainer0>& x)
243 : _map(x.
index_map()), _bs(x.
bs()), _x(x._x.begin(), x._x.end()),
244 _scatterer(scatter_ptr(x._scatterer)),
245 _buffer_local(_bs * _scatterer->local_indices_block().size()),
246 _buffer_remote(_bs * _scatterer->remote_indices_block().size())
264 [[deprecated(
"Use std::ranges::fill(u.array(), v) instead.")]]
void
267 std::ranges::fill(_x, v);
285 template <
typename U,
typename GetPtr>
290 pack(_scatterer->local_indices_block().begin(),
291 _scatterer->local_indices_block().end(), _x.begin(),
292 _buffer_local.begin());
293 _scatterer->scatter_fwd_begin(get_ptr(_buffer_local),
294 get_ptr(_buffer_remote), _bs,
308 requires requires(Container c) {
309 { c.data() } -> std::same_as<T*>;
329 template <
typename U>
330 requires VectorPackKernel<U, container_type, ScatterContainer>
333 _scatterer->scatter_fwd_end(_request.request());
334 unpack(_scatterer->remote_indices_block().begin(),
335 _scatterer->remote_indices_block().end(), _buffer_remote.begin(),
336 std::next(_x.begin(), _bs * _map->size_local()));
350 requires requires(Container c) {
351 { c.data() } -> std::same_as<T*>;
368 requires requires(Container c) {
369 { c.data() } -> std::same_as<T*>;
390 template <
typename U,
typename GetPtr>
391 requires VectorPackKernel<U, container_type, ScatterContainer>
392 and GetPtrConcept<GetPtr, Container, T>
395 std::int32_t local_size = _bs * _map->size_local();
396 pack(_scatterer->remote_indices_block().begin(),
397 _scatterer->remote_indices_block().end(),
398 std::next(_x.begin(), local_size), _buffer_remote.begin());
399 _scatterer->scatter_rev_begin(get_ptr(_buffer_remote),
400 get_ptr(_buffer_local), _bs,
414 requires requires(Container c) {
415 { c.data() } -> std::same_as<T*>;
432 template <
typename U>
433 requires VectorPackKernel<U, container_type, ScatterContainer>
436 _scatterer->scatter_rev_end(_request.request());
437 unpack(_scatterer->local_indices_block().begin(),
438 _scatterer->local_indices_block().end(), _buffer_local.begin(),
454 template <
class BinaryOperation>
455 requires requires(Container c) {
456 { c.data() } -> std::same_as<T*>;
465 std::shared_ptr<const common::IndexMap>
index_map() const noexcept
472 std::shared_ptr<const common::Scatterer<ScatterContainer>>
479 constexpr int bs() const noexcept {
return _bs; }
501 std::shared_ptr<const common::IndexMap> _map;
510 std::shared_ptr<const common::Scatterer<ScatterContainer>> _scatterer;
533 using T =
typename V::value_type;
534 const std::int32_t local_size = a.bs() * a.index_map()->size_local();
535 if (local_size != b.bs() * b.index_map()->size_local())
536 throw std::invalid_argument(
"Incompatible vector sizes");
538 const T local = std::transform_reduce(
539 a.array().begin(), std::next(a.array().begin(), local_size),
540 b.array().begin(),
static_cast<T
>(0), std::plus{},
543 if constexpr (std::is_same<T, std::complex<double>>::value
544 or std::is_same<T, std::complex<float>>::value)
546 return std::conj(a) * b;
554 a.index_map()->comm());
564 using T =
typename V::value_type;
566 return std::real(result);
578 using T =
typename V::value_type;
583 std::int32_t size_local = x.bs() * x.index_map()->size_local();
584 using U =
typename dolfinx::scalar_value_t<T>;
585 U local_l1 = std::accumulate(
586 x.array().begin(), std::next(x.array().begin(), size_local), U(0),
587 [](
auto norm,
auto x) {
return norm + std::abs(x); });
590 x.index_map()->comm());
597 std::int32_t size_local = x.bs() * x.index_map()->size_local();
598 auto max_pos = std::max_element(
599 x.array().begin(), std::next(x.array().begin(), size_local),
600 [](T a, T b) { return std::norm(a) < std::norm(b); });
601 auto local_linf = std::abs(*max_pos);
602 decltype(local_linf) linf = 0;
603 MPI_Allreduce(&local_linf, &linf, 1,
MPI::mpi_t<
decltype(linf)>, MPI_MAX,
604 x.index_map()->comm());
608 throw std::invalid_argument(
"Norm type not supported");
621 using T =
typename V::value_type;
622 using U =
typename dolfinx::scalar_value_t<T>;
625 for (std::size_t i = 0; i < basis.size(); ++i)
629 V& bi = basis[i].get();
630 for (std::size_t j = 0; j < i; ++j)
632 const V& bj = basis[j].get();
636 std::ranges::transform(bj.array(), bi.array(), bi.array().begin(),
637 [dot_ij](
auto xj,
auto xi)
638 { return xi - dot_ij * xj; });
643 if (
norm *
norm < std::numeric_limits<U>::epsilon())
645 throw std::runtime_error(
646 "Linear dependency detected. Cannot orthogonalize.");
648 std::ranges::transform(bi.array(), bi.array().begin(),
649 [
norm](
auto x) { return x / norm; });
663 std::vector<std::reference_wrapper<const V>> basis,
664 dolfinx::scalar_value_t<typename V::value_type> eps = std::numeric_limits<
665 dolfinx::scalar_value_t<typename V::value_type>>::epsilon())
667 using T =
typename V::value_type;
668 for (std::size_t i = 0; i < basis.size(); i++)
670 for (std::size_t j = i; j < basis.size(); ++j)
672 T delta_ij = (i == j) ? T(1) : T(0);
674 if (std::norm(delta_ij - dot_ij) > eps)
Holder for the request of a non-blocking operation.
Definition MPI.h:421
A Scatterer supports the scattering and gathering of distributed data that is associated with a commo...
Definition Scatterer.h:87
A vector that can be distributed across processes.
Definition Vector.h:53
std::shared_ptr< const common::IndexMap > index_map() const noexcept
Get IndexMap.
Definition Vector.h:465
container_type::value_type value_type
Scalar type.
Definition Vector.h:151
void scatter_rev_begin(U pack, GetPtr get_ptr)
Start scatter (send) of ghost entry data to the owning process of an index.
Definition Vector.h:393
Vector(const Vector< T0, Container0, ScatterContainer0 > &x)
Create a vector by copying and converting another vector.
Definition Vector.h:242
container_type & mutable_array() noexcept
Get local part of the vector.
Definition Vector.h:494
Vector(std::shared_ptr< const common::IndexMap > map, int bs)
Create a distributed vector.
Definition Vector.h:168
void scatter_rev(BinaryOperation op)
Scatter (send) of ghost data values to the owning process and assign/accumulate into the owned data e...
Definition Vector.h:458
constexpr int bs() const noexcept
Get block size.
Definition Vector.h:479
void scatter_fwd_end(U unpack)
End scatter (send) of local data values that are ghosted on other processes.
Definition Vector.h:331
container_type & array() noexcept
Get the process-local part of the vector.
Definition Vector.h:484
void scatter_rev_end(U unpack)
End scatter of ghost data to owner and update owned entries.
Definition Vector.h:434
Vector & operator=(Vector &&x)=default
void scatter_fwd_end()
End scatter (send) of local data values that are ghosted on other processes (simplified CPU version).
Definition Vector.h:349
void scatter_fwd()
Scatter (send) of local data values that are ghosted on other processes and update ghost entry values...
Definition Vector.h:367
Container container_type
Container type.
Definition Vector.h:148
void scatter_fwd_begin(U pack, GetPtr get_ptr)
Begin scatter (send) of local data that is ghosted on other processes.
Definition Vector.h:288
void set(value_type v)
Set all entries (including ghosts).
Definition Vector.h:265
Vector(Vector &&x)=default
const container_type & array() const noexcept
Get the process-local part of the vector (const version).
Definition Vector.h:489
Vector(std::shared_ptr< const common::IndexMap > map, int bs, std::shared_ptr< const common::Scatterer< ScatterContainer > > scatterer)
Create a distributed vector using an existing scatterer.
Definition Vector.h:180
std::shared_ptr< const common::Scatterer< ScatterContainer > > scatterer() const noexcept
Get the scatterer used for halo communication.
Definition Vector.h:473
void scatter_fwd_begin()
Begin scatter (send) of local data that is ghosted on other processes (simplified CPU version).
Definition Vector.h:307
Vector(const Vector &x)=default
void scatter_rev_begin()
Start scatter (send) of ghost entry data to the owning process of an index (simplified CPU version).
Definition Vector.h:413
Access to pointer function concept.
Definition Vector.h:36
la::Vector scatter pack/unpack function concept.
Definition Vector.h:30
MPI_Datatype mpi_t
Retrieves the MPI data type associated to the provided type.
Definition MPI.h:326
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
Linear algebra interface.
Definition dolfinx_la.h:7
void orthonormalize(std::vector< std::reference_wrapper< V > > basis)
Orthonormalize a set of vectors.
Definition Vector.h:619
auto squared_norm(const V &a)
Compute the squared L2 norm of vector.
Definition Vector.h:562
auto norm(const V &x, Norm type=Norm::l2)
Compute the norm of the vector.
Definition Vector.h:576
auto inner_product(const V &a, const V &b)
Compute the inner product of two vectors.
Definition Vector.h:531
bool is_orthonormal(std::vector< std::reference_wrapper< const V > > basis, dolfinx::scalar_value_t< typename V::value_type > eps=std::numeric_limits< dolfinx::scalar_value_t< typename V::value_type > >::epsilon())
Test if basis is orthonormal.
Definition Vector.h:662
Norm
Norm types.
Definition utils.h:22