19#ifdef DEAL_II_WITH_PSBLAS
20# include <psb_base_cbind.h>
21# include <psb_c_base.h>
22# include <psb_c_dbase.h>
26namespace PSCToolkitWrappers
30 : psblas_vector(nullptr)
32 , psblas_descriptor(nullptr)
33 , communicator(MPI_COMM_NULL)
37 , remote_entries_pending(false)
45 reinit(v.owned_elements, v.ghost_indices, v.communicator);
47 reinit(v.owned_elements, v.communicator);
55 if (state != internal::State::Default)
58 ierr = psb_c_dgefree(psblas_vector, psblas_descriptor.get());
68 psblas_vector =
nullptr;
71 reinit(local_partitioning, communicator);
81 psblas_vector =
nullptr;
84 reinit(local_partitioning, ghost_indices, communicator);
92 const bool omit_zeroing_entries)
95 ExcMessage(
"MPI_COMM_NULL passed to Vector::reinit()."));
101 const bool partitioning_changes_locally =
102 (psblas_descriptor.get() ==
nullptr) || (ghosted ==
true) ||
103 (communicator !=
comm) ||
104 (owned_elements.size() != local_partitioning.
size()) ||
105 (owned_elements != local_partitioning);
110 const bool partitioning_will_change =
115 owned_elements = local_partitioning;
120 if (partitioning_will_change ==
true)
122 psblas_descriptor.reset(psb_c_new_descriptor(),
123 internal::DescriptorDeleter());
126 const std::vector<types::global_dof_index> &indexes =
129 const auto number_of_local_indexes =
132 std::vector<psb_l_t> vl(number_of_local_indexes);
133 for (std::size_t i = 0; i < number_of_local_indexes; ++i)
135 const auto psblas_index =
static_cast<psb_l_t
>(indexes[i]);
137 vl[i] = psblas_index;
141 psblas_context = InitFinalize::get_psblas_context();
142 ierr = psb_c_cdall_vl(number_of_local_indexes,
145 psblas_descriptor.get());
148 Assert(ierr == 0, ExcInitializePSBLASDescriptor(ierr));
152 psblas_vector = psb_c_new_dvector();
154 ierr = psb_c_dgeall_remote_options(psblas_vector,
155 psblas_descriptor.get(),
158 Assert(ierr == 0, ExcInitializePSBLASVector(ierr));
160 if (omit_zeroing_entries ==
false)
162 ierr = psb_c_dvect_set_scal(psblas_vector, 0.0);
164 ExcCallingPSBLASFunction(ierr,
"psb_c_dvect_set_scal"));
167 state = internal::State::Assembled;
169 remote_entries_pending =
false;
180 ExcMessage(
"MPI_COMM_NULL passed to Vector::reinit()."));
182 IndexSet new_ghost_indices = ghosts;
189 const bool partitioning_changes_locally =
190 (psblas_descriptor.get() ==
nullptr) || (ghosted ==
false) ||
191 (communicator !=
comm) ||
192 (owned_elements.size() != local_partitioning.
size()) ||
193 (owned_elements != local_partitioning) ||
194 (ghost_indices.size() != new_ghost_indices.
size()) ||
195 (ghost_indices != new_ghost_indices);
199 const bool partitioning_will_change =
204 owned_elements = local_partitioning;
205 ghost_indices = std::move(new_ghost_indices);
207 owned_elements.compress();
210 if (partitioning_will_change ==
true)
212 psblas_descriptor.reset(psb_c_new_descriptor(),
213 internal::DescriptorDeleter());
216 const std::vector<types::global_dof_index> &indexes =
219 const auto number_of_local_indexes =
222 std::vector<psb_l_t> vl(number_of_local_indexes);
223 std::vector<psb_i_t> lidx(number_of_local_indexes);
224 for (std::size_t i = 0; i < number_of_local_indexes; ++i)
226 const auto psblas_index =
static_cast<psb_l_t
>(indexes[i]);
227 const auto idx =
static_cast<psb_i_t
>(i);
230 vl[i] = psblas_index;
241 psblas_context = InitFinalize::get_psblas_context();
242 ierr = psb_c_cdall_vl_lidx(number_of_local_indexes,
246 psblas_descriptor.get());
248 Assert(ierr == 0, ExcInitializePSBLASDescriptor(ierr));
251 const std::vector<types::global_dof_index> &ghost_indexes =
252 ghost_indices.get_index_vector();
253 const auto number_of_ghost_indices = ghost_indexes.size();
255 std::vector<psb_l_t> global_ghost_indices(number_of_ghost_indices);
256 std::vector<psb_i_t> local_ghost_indices(number_of_ghost_indices);
258 psb_i_t extended_idx_counter = number_of_local_indexes;
259 for (std::size_t i = 0; i < number_of_ghost_indices; ++i)
261 const auto psblas_index =
static_cast<psb_l_t
>(ghost_indexes[i]);
263 global_ghost_indices[i] = psblas_index;
264 const auto idx =
static_cast<psb_i_t
>(extended_idx_counter);
266 local_ghost_indices[i] = extended_idx_counter++;
270 ierr = psb_c_cdins_lidx(number_of_ghost_indices,
271 global_ghost_indices.data(),
272 local_ghost_indices.data(),
273 psblas_descriptor.get());
275 Assert(ierr == 0, ExcCallingPSBLASFunction(ierr,
"psb_c_cdins_lidx"));
280 if (!psb_c_cd_is_asb(psblas_descriptor.get()))
282 ierr = psb_c_cdasb(psblas_descriptor.get());
283 Assert(ierr == 0, ExcAssemblePSBLASDescriptor(ierr));
287 psblas_vector = psb_c_new_dvector();
289 ierr = psb_c_dgeall_remote_options(psblas_vector,
290 psblas_descriptor.get(),
293 Assert(ierr == 0, ExcInitializePSBLASVector(ierr));
298 ierr = psb_c_dgeasb_options(psblas_vector,
299 psblas_descriptor.get(),
301 Assert(ierr == 0, ExcAssemblePSBLASVector(ierr));
303 state = internal::State::Assembled;
305 remote_entries_pending =
false;
313 psblas_descriptor = v.psblas_descriptor;
319 if (!omit_zeroing_entries)
321 int ierr = psb_c_dvect_set_scal(psblas_vector, 0.0);
323 ExcCallingPSBLASFunction(ierr,
"psb_c_dvect_set_scal"));
330 omit_zeroing_entries);
333 if (!psb_c_cd_is_asb(psblas_descriptor.get()))
335 ierr = psb_c_cdasb(psblas_descriptor.get());
336 Assert(ierr == 0, ExcAssemblePSBLASDescriptor(ierr));
338 ierr = psb_c_dgeasb_options(psblas_vector,
339 psblas_descriptor.get(),
341 Assert(ierr == 0, ExcAssemblePSBLASVector(ierr));
354 Assert(v.state == internal::State::Assembled,
355 ExcInvalidStateAssembled(v.state));
361 psblas_descriptor = v.psblas_descriptor;
376 psblas_descriptor.get());
383 state = internal::State::Assembled;
384 remote_entries_pending =
false;
396 int ierr = psb_c_dvect_set_scal(psblas_vector, s);
397 Assert(ierr == 0, ExcCallingPSBLASFunction(ierr,
"psb_c_dvect_set_scal"));
412 Vector::get_psblas_descriptor()
const
414 return psblas_descriptor.get();
420 Vector::get_psblas_vector()
const
422 return psblas_vector;
430 if (state != internal::State::Default)
432 int ierr = psb_c_dgefree(psblas_vector, psblas_descriptor.get());
433 Assert(ierr == 0, ExcFreePSBLASVector(ierr));
436 psblas_vector =
nullptr;
437 owned_elements.clear();
438 owned_elements.set_size(0);
439 ghost_indices.clear();
440 owned_elements.set_size(0);
441 state = internal::State::Default;
443 remote_entries_pending =
false;
452 Assert(state == internal::State::Assembled,
453 ExcInvalidStateAssembled(state));
454 return psb_c_dgenrmi(psblas_vector, psblas_descriptor.get());
462 Assert(state == internal::State::Assembled,
463 ExcInvalidStateAssembled(state));
464 return psb_c_dgeasum(psblas_vector, psblas_descriptor.get());
472 Assert(state == internal::State::Assembled,
473 ExcInvalidStateAssembled(state));
474 return psb_c_dgenrm2(psblas_vector, psblas_descriptor.get());
482 const value_type *start_ptr = psb_c_dvect_f_get_pnt(psblas_vector);
486 for (
const value_type *ptr = start_ptr; ptr != end_ptr; ++ptr)
487 local_sum_of_values += *ptr;
499 const value_type *start_ptr = psb_c_dvect_f_get_pnt(psblas_vector);
500 Assert(start_ptr !=
nullptr,
501 ExcMessage(
"Error getting underlying PSBLAS vector."));
503 const bool has_nonzero_local =
504 std::any_of(start_ptr,
508 unsigned int num_nonzero =
510 return num_nonzero == 0;
523 int ierr = psb_c_dgeaxpby(
524 a, v.psblas_vector, 0.0, psblas_vector, psblas_descriptor.get());
533 return owned_elements.n_elements();
542 return psb_c_dgedot(psblas_vector,
544 psblas_descriptor.get());
558 psblas_descriptor.get());
573 psblas_descriptor.get());
580 Vector::set(
const std::vector<Vector::size_type> &indices,
581 const std::vector<Vector::value_type> &values)
587 value_type *
const local_values = psb_c_dvect_f_get_pnt(psblas_vector);
589 for (std::size_t i = 0; i < indices.size(); ++i)
591 Assert(owned_elements.is_element(indices[i]),
592 ExcMessage(
"You are trying to write to an element of the vector "
593 "that is not locally owned. This is not allowed for "
594 "the current interface to PSBLAS vectors."));
595 local_values[owned_elements.index_within_set(indices[i])] =
values[i];
602 Vector::add(
const std::vector<Vector::size_type> &indices,
603 const std::vector<Vector::value_type> &values)
608 ExcMessage(
"Indices and values size mismatch."));
610 value_type *
const local_values = psb_c_dvect_f_get_pnt(psblas_vector);
614 std::vector<psb_l_t> irw;
615 std::vector<psb_d_t> val;
617 for (std::size_t i = 0; i < indices.size(); ++i)
618 if (owned_elements.is_element(indices[i]))
619 local_values[owned_elements.index_within_set(indices[i])] +=
values[i];
622 const auto psblas_index =
static_cast<psb_l_t
>(indices[i]);
624 irw.push_back(psblas_index);
628 if (irw.empty() ==
false)
630 const auto nz =
static_cast<psb_i_t
>(irw.size());
633 const int ierr = psb_c_dgeins(
634 nz, irw.data(), val.data(), psblas_vector, psblas_descriptor.get());
635 Assert(ierr == 0, ExcInsertionInPSBLASVector(ierr));
637 remote_entries_pending =
true;
648 int ierr = psb_c_dgeaxpby(s,
652 psblas_descriptor.get());
653 Assert(ierr == 0, ExcAXPBY(ierr));
663 value_type *start_ptr = psb_c_dvect_f_get_pnt(psblas_vector);
665 while (start_ptr != end_ptr)
683 psblas_descriptor.get());
684 Assert(ierr == 0, ExcAXPBY(ierr));
693 int ierr = psb_c_dgeaxpby(
694 a,
V.psblas_vector, s, psblas_vector, psblas_descriptor.get());
695 Assert(ierr == 0, ExcAXPBY(ierr));
704 value_type *start_ptr = psb_c_dvect_f_get_pnt(psblas_vector);
705 value_type *start_ptr_v = psb_c_dvect_f_get_pnt(v.psblas_vector);
707 while (start_ptr != end_ptr)
709 *start_ptr *= (*start_ptr_v);
723 return psb_c_dgedot(psblas_vector,
725 psblas_descriptor.get());
734 std::swap(psblas_vector, v.psblas_vector);
735 std::swap(psblas_descriptor, v.psblas_descriptor);
736 std::swap(ghosted, v.ghosted);
737 std::swap(this->last_action, v.last_action);
738 std::swap(communicator, v.communicator);
739 std::swap(state, v.state);
740 std::swap(remote_entries_pending, v.remote_entries_pending);
741 std::swap(owned_elements, v.owned_elements);
744 ghost_indices = v.ghost_indices;
745 v.ghost_indices = temp;
754 ExcMessage(
"Calling compress() is only useful if a vector "
755 "has been written into, but this is a vector with ghost "
756 "elements and consequently is read-only. It does "
757 "not make sense to call compress() for such "
761 Assert(state != internal::State::Default, ExcInvalidDefault());
766 "Missing compress() or calling with wrong VectorOperation argument."));
770 if (!psb_c_cd_is_asb(psblas_descriptor.get()))
772 ierr = psb_c_cdasb(psblas_descriptor.get());
773 Assert(ierr == 0, ExcAssemblePSBLASDescriptor(ierr));
792 ierr = psb_c_dgereinit(psblas_vector, psblas_descriptor.get(),
false);
793 Assert(ierr == 0, ExcCallingPSBLASFunction(ierr,
"psb_c_dgereinit"));
799 const std::vector<types::global_dof_index> &indices =
800 owned_elements.get_index_vector();
802 psb_c_dvect_f_get_pnt(psblas_vector);
804 std::vector<psb_l_t> irw(indices.size());
805 std::vector<psb_d_t> val(indices.size());
806 for (std::size_t i = 0; i < indices.size(); ++i)
808 const auto psblas_index =
static_cast<psb_l_t
>(indices[i]);
810 irw[i] = psblas_index;
811 val[i] = local_values[i];
814 const auto nz =
static_cast<psb_i_t
>(irw.size());
818 nz, irw.data(), val.data(), psblas_vector, psblas_descriptor.get());
819 Assert(ierr == 0, ExcInsertionInPSBLASVector(ierr));
822 ierr = psb_c_dgeasb_options(psblas_vector,
823 psblas_descriptor.get(),
827 Assert(ierr == 0, ExcAssemblePSBLASVector(ierr));
829 remote_entries_pending =
false;
832 state = internal::State::Assembled;
843 int ierr = psb_c_dhalo(psblas_vector, psblas_descriptor.get());
void subtract_set(const IndexSet &other)
std::vector< size_type > get_index_vector() const
bool has_ghost_elements() const
void add(const std::vector< size_type > &indices, const std::vector< OtherNumber > &values)
Vector< Number > & operator=(const Number s)
Number operator*(const Vector< Number2 > &V) const
Number mean_value() const
Number add_and_dot(const Number a, const Vector< Number > &V, const Vector< Number > &W)
MPI_Comm get_mpi_communicator() const
virtual size_type size() const override
void equ(const Number a, const Vector< Number > &u)
void sadd(const Number s, const Vector< Number > &V)
real_type l2_norm() const
virtual ~Vector() override=default
real_type linfty_norm() const
Vector< Number > & operator+=(const Vector< Number > &V)
void scale(const Vector< Number > &scaling_factors)
IndexSet locally_owned_elements() const
AlignedVector< Number > values
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
size_type locally_owned_size() const
virtual void swap(Vector< Number > &v) noexcept
void compress(VectorOperation::values operation=VectorOperation::unknown) const
Vector< Number > & operator-=(const Vector< Number > &V)
void update_ghost_values() const
std::size_t memory_consumption() const
real_type l1_norm() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define AssertIntegerConversion(index1, index2)
static ::ExceptionBase & ExcGhostsPresent()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
#define AssertNothrow(cond, exc)
static ::ExceptionBase & ExcInvalidState()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
T sum(const T &t, const MPI_Comm mpi_communicator)
T logical_or(const T &t, const MPI_Comm mpi_communicator)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)