13#include <dolfinx/common/IndexMap.h>
14#include <dolfinx/common/Scatterer.h>
15#include <dolfinx/common/types.h>
27template <
class F,
class Container,
class ScatterContainer>
29 f(idx.cbegin(), idx.cend(), x.cbegin(), x.begin());
33template <
class GetPtr,
class U,
class T>
35 { f(x) } -> std::same_as<T*>;
36} and
requires(GetPtr f,
const U x) {
37 { f(x) } -> std::same_as<const T*>;
48template <
typename T,
typename Container = std::vector<T>,
49 typename ScatterContainer = std::vector<std::
int32_t>>
52 static_assert(std::is_same_v<typename Container::value_type, T>);
54 template <
typename,
typename,
typename>
66 static void dispatch_bs(
int bs, F&& f)
71 return f(std::integral_constant<int, 1>{});
73 return f(std::integral_constant<int, 2>{});
75 return f(std::integral_constant<int, 3>{});
87 return [
bs = _bs](
typename ScatterContainer::const_iterator idx_first,
88 typename ScatterContainer::const_iterator idx_last,
89 const auto in_first,
auto out_first)
96 for (
auto idx = idx_first; idx != idx_last; ++idx)
98 auto in = std::next(in_first, (*idx) * B);
99 for (
int j = 0; j < B; ++j, ++in, ++out)
114 return get_unpack_op([](
auto,
auto received) {
return received; });
122 template <
typename BinaryOp>
123 auto get_unpack_op(BinaryOp op)
125 return [op,
bs = _bs](
typename ScatterContainer::const_iterator idx_first,
126 typename ScatterContainer::const_iterator idx_last,
127 const auto in_first,
auto out_first)
134 for (
auto idx = idx_first; idx != idx_last; ++idx)
136 auto out = std::next(out_first, (*idx) * B);
137 for (
int j = 0; j < B; ++j, ++in, ++out)
138 *out = op(*out, *in);
151 static_assert(std::is_same_v<value_type, typename container_type::value_type>,
152 "Scalar type and container value type must be the same.");
166 Vector(std::shared_ptr<const common::IndexMap> map,
int bs)
168 std::make_shared<
common::Scatterer<ScatterContainer>>(*map))
178 Vector(std::shared_ptr<const common::IndexMap> map,
int bs,
180 : _map(std::move(map)), _bs(
bs),
181 _x(
bs * (_map->size_local() + _map->num_ghosts())),
183 _buffer_local(
bs * _scatterer->local_indices_block().size()),
184 _buffer_remote(
bs * _scatterer->remote_indices_block().size())
204 std::shared_ptr<const common::Scatterer<ScatterContainer>>
205 scatter_ptr(
auto sc)
const
207 using SC =
typename std::remove_cv<
208 typename decltype(sc)::element_type>::type::container_type;
209 if constexpr (std::is_same_v<ScatterContainer, SC>)
212 return std::make_shared<common::Scatterer<ScatterContainer>>(*sc);
235 template <
typename T0,
typename Container0,
typename ScatterContainer0>
236 explicit Vector(
const Vector<T0, Container0, ScatterContainer0>& x)
237 : _map(x.
index_map()), _bs(x.
bs()), _x(x._x.begin(), x._x.end()),
238 _scatterer(scatter_ptr(x._scatterer)), _request(MPI_REQUEST_NULL),
239 _buffer_local(_bs * _scatterer->local_indices_block().size()),
240 _buffer_remote(_bs * _scatterer->remote_indices_block().size())
254 [[deprecated(
"Use std::ranges::fill(u.array(), v) instead.")]]
void
257 std::ranges::fill(_x, v);
275 template <
typename U,
typename GetPtr>
280 pack(_scatterer->local_indices_block().begin(),
281 _scatterer->local_indices_block().end(), _x.begin(),
282 _buffer_local.begin());
283 _scatterer->scatter_fwd_begin(get_ptr(_buffer_local),
284 get_ptr(_buffer_remote), _bs, _request);
297 requires requires(Container c) {
298 { c.data() } -> std::same_as<T*>;
318 template <
typename U>
319 requires VectorPackKernel<U, container_type, ScatterContainer>
322 _scatterer->scatter_fwd_end(_request);
323 unpack(_scatterer->remote_indices_block().begin(),
324 _scatterer->remote_indices_block().end(), _buffer_remote.begin(),
325 std::next(_x.begin(), _bs * _map->size_local()));
339 requires requires(Container c) {
340 { c.data() } -> std::same_as<T*>;
357 requires requires(Container c) {
358 { c.data() } -> std::same_as<T*>;
379 template <
typename U,
typename GetPtr>
380 requires VectorPackKernel<U, container_type, ScatterContainer>
381 and GetPtrConcept<GetPtr, Container, T>
384 std::int32_t local_size = _bs * _map->size_local();
385 pack(_scatterer->remote_indices_block().begin(),
386 _scatterer->remote_indices_block().end(),
387 std::next(_x.begin(), local_size), _buffer_remote.begin());
388 _scatterer->scatter_rev_begin(get_ptr(_buffer_remote),
389 get_ptr(_buffer_local), _bs, _request);
402 requires requires(Container c) {
403 { c.data() } -> std::same_as<T*>;
420 template <
typename U>
421 requires VectorPackKernel<U, container_type, ScatterContainer>
424 _scatterer->scatter_rev_end(_request);
425 unpack(_scatterer->local_indices_block().begin(),
426 _scatterer->local_indices_block().end(), _buffer_local.begin(),
442 template <
class BinaryOperation>
443 requires requires(Container c) {
444 { c.data() } -> std::same_as<T*>;
453 std::shared_ptr<const common::IndexMap>
index_map() const noexcept
460 std::shared_ptr<const common::Scatterer<ScatterContainer>>
467 constexpr int bs() const noexcept {
return _bs; }
489 std::shared_ptr<const common::IndexMap> _map;
498 std::shared_ptr<const common::Scatterer<ScatterContainer>> _scatterer;
501 MPI_Request _request = MPI_REQUEST_NULL;
520 using T =
typename V::value_type;
521 const std::int32_t local_size = a.bs() * a.index_map()->size_local();
522 if (local_size != b.bs() * b.index_map()->size_local())
523 throw std::runtime_error(
"Incompatible vector sizes");
525 const T local = std::transform_reduce(
526 a.array().begin(), std::next(a.array().begin(), local_size),
527 b.array().begin(),
static_cast<T
>(0), std::plus{},
530 if constexpr (std::is_same<T, std::complex<double>>::value
531 or std::is_same<T, std::complex<float>>::value)
533 return std::conj(a) * b;
541 a.index_map()->comm());
551 using T =
typename V::value_type;
553 return std::real(result);
565 using T =
typename V::value_type;
570 std::int32_t size_local = x.bs() * x.index_map()->size_local();
571 using U =
typename dolfinx::scalar_value_t<T>;
572 U local_l1 = std::accumulate(
573 x.array().begin(), std::next(x.array().begin(), size_local), U(0),
574 [](
auto norm,
auto x) {
return norm + std::abs(x); });
577 x.index_map()->comm());
584 std::int32_t size_local = x.bs() * x.index_map()->size_local();
585 auto max_pos = std::max_element(
586 x.array().begin(), std::next(x.array().begin(), size_local),
587 [](T a, T b) { return std::norm(a) < std::norm(b); });
588 auto local_linf = std::abs(*max_pos);
589 decltype(local_linf) linf = 0;
590 MPI_Allreduce(&local_linf, &linf, 1,
MPI::mpi_t<
decltype(linf)>, MPI_MAX,
591 x.index_map()->comm());
595 throw std::runtime_error(
"Norm type not supported");
608 using T =
typename V::value_type;
609 using U =
typename dolfinx::scalar_value_t<T>;
612 for (std::size_t i = 0; i < basis.size(); ++i)
616 V& bi = basis[i].get();
617 for (std::size_t j = 0; j < i; ++j)
619 const V& bj = basis[j].get();
623 std::ranges::transform(bj.array(), bi.array(), bi.array().begin(),
624 [dot_ij](
auto xj,
auto xi)
625 { return xi - dot_ij * xj; });
630 if (
norm *
norm < std::numeric_limits<U>::epsilon())
632 throw std::runtime_error(
633 "Linear dependency detected. Cannot orthogonalize.");
635 std::ranges::transform(bi.array(), bi.array().begin(),
636 [
norm](
auto x) { return x / norm; });
650 std::vector<std::reference_wrapper<const V>> basis,
651 dolfinx::scalar_value_t<typename V::value_type> eps = std::numeric_limits<
652 dolfinx::scalar_value_t<typename V::value_type>>::epsilon())
654 using T =
typename V::value_type;
655 for (std::size_t i = 0; i < basis.size(); i++)
657 for (std::size_t j = i; j < basis.size(); ++j)
659 T delta_ij = (i == j) ? T(1) : T(0);
661 if (std::norm(delta_ij - dot_ij) > eps)
A Scatterer supports the scattering and gathering of distributed data that is associated with a commo...
Definition Scatterer.h:84
A vector that can be distributed across processes.
Definition Vector.h:51
std::shared_ptr< const common::IndexMap > index_map() const noexcept
Get IndexMap.
Definition Vector.h:453
container_type::value_type value_type
Scalar type.
Definition Vector.h:149
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:382
Vector(const Vector< T0, Container0, ScatterContainer0 > &x)
Create a vector by copying and converting another vector.
Definition Vector.h:236
container_type & mutable_array() noexcept
Get local part of the vector.
Definition Vector.h:482
Vector(std::shared_ptr< const common::IndexMap > map, int bs)
Create a distributed vector.
Definition Vector.h:166
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:446
constexpr int bs() const noexcept
Get block size.
Definition Vector.h:467
void scatter_fwd_end(U unpack)
End scatter (send) of local data values that are ghosted on other processes.
Definition Vector.h:320
container_type & array() noexcept
Get the process-local part of the vector.
Definition Vector.h:472
void scatter_rev_end(U unpack)
End scatter of ghost data to owner and update owned entries.
Definition Vector.h:422
Vector & operator=(Vector &&x)=default
Move assignment operator.
void scatter_fwd_end()
End scatter (send) of local data values that are ghosted on other processes (simplified CPU version).
Definition Vector.h:338
void scatter_fwd()
Scatter (send) of local data values that are ghosted on other processes and update ghost entry values...
Definition Vector.h:356
Container container_type
Container type.
Definition Vector.h:146
void scatter_fwd_begin(U pack, GetPtr get_ptr)
Begin scatter (send) of local data that is ghosted on other processes.
Definition Vector.h:278
void set(value_type v)
Set all entries (including ghosts).
Definition Vector.h:255
Vector(Vector &&x)=default
Move constructor.
const container_type & array() const noexcept
Get the process-local part of the vector (const version).
Definition Vector.h:477
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:178
std::shared_ptr< const common::Scatterer< ScatterContainer > > scatterer() const noexcept
Get the scatterer used for halo communication.
Definition Vector.h:461
void scatter_fwd_begin()
Begin scatter (send) of local data that is ghosted on other processes (simplified CPU version).
Definition Vector.h:296
Vector(const Vector &x)=default
Copy constructor.
void scatter_rev_begin()
Start scatter (send) of ghost entry data to the owning process of an index (simplified CPU version).
Definition Vector.h:401
Access to pointer function concept.
Definition Vector.h:34
la::Vector scatter pack/unpack function concept.
Definition Vector.h:28
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:606
auto squared_norm(const V &a)
Compute the squared L2 norm of vector.
Definition Vector.h:549
auto norm(const V &x, Norm type=Norm::l2)
Compute the norm of the vector.
Definition Vector.h:563
auto inner_product(const V &a, const V &b)
Compute the inner product of two vectors.
Definition Vector.h:518
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:649
Norm
Norm types.
Definition utils.h:17