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())