2#ifndef DUNE_PDELAB_BACKEND_ISTL_GENEO_SUBDOMAINPROJECTEDCOARSESPACE_HH
3#define DUNE_PDELAB_BACKEND_ISTL_GENEO_SUBDOMAINPROJECTEDCOARSESPACE_HH
10#include <dune/pdelab/backend/istl/geneo/multicommdatahandle.hh>
12#include <dune/pdelab/backend/istl/geneo/coarsespace.hh>
13#include <dune/pdelab/backend/istl/geneo/subdomainbasis.hh>
26 template<
class GFS,
class M,
class X,
class PIH>
30 typedef int rank_type;
43 : gfs_(gfs), AF_exterior_(AF_exterior_),
44 verbosity_(verbosity),
45 ranks_(gfs.gridView().comm().
size()),
46 my_rank_(gfs.gridView().comm().rank()),
47 subdomainbasis_(subdomainbasis)
49 neighbor_ranks_ = parallelhelper.getNeighborRanks();
51 setup_coarse_system();
55 void setup_coarse_system() {
56 using Dune::PDELab::Backend::native;
59 gfs_.gridView().comm().barrier();
60 if (my_rank_ == 0 && verbosity_ > 0) std::cout <<
"Matrix setup" << std::endl;
64 local_basis_sizes_.resize(ranks_);
65 rank_type local_size = subdomainbasis_->basis_size();
66 gfs_.gridView().comm().allgather(&local_size, 1, local_basis_sizes_.data());
69 global_basis_size_ = 0;
70 for (rank_type n : local_basis_sizes_) {
71 global_basis_size_ += n;
73 my_basis_array_offset_ = basis_array_offset(my_rank_);
74 rank_type max_local_basis_size = *std::max_element(local_basis_sizes_.begin(),local_basis_sizes_.end());
76 if (my_rank_ == 0 && verbosity_ > 0) std::cout <<
"Global basis size B=" << global_basis_size_ << std::endl;
79 coarse_system_ = std::make_shared<COARSE_M>(global_basis_size_, global_basis_size_,
COARSE_M::row_wise);
83 std::vector<std::vector<std::vector<field_type> > > local_rows(local_basis_sizes_[my_rank_]);
84 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[my_rank_]; basis_index++) {
85 local_rows[basis_index].resize(neighbor_ranks_.size()+1);
89 std::vector<std::shared_ptr<X> > neighbor_basis(neighbor_ranks_.size());
90 for (
auto& basis : neighbor_basis) {
91 basis = std::make_shared<X>(gfs_, 0.0);
95 for (rank_type basis_index_remote = 0; basis_index_remote < max_local_basis_size; basis_index_remote++) {
99 if (basis_index_remote < local_basis_sizes_[my_rank_]) {
109 if (basis_index_remote < local_basis_sizes_[my_rank_]) {
110 auto basis_vector = *subdomainbasis_->get_basis_vector(basis_index_remote);
112 native(AF_exterior_).mv(native(basis_vector), native(Atimesv));
113 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[my_rank_]; basis_index++) {
114 field_type entry = *subdomainbasis_->get_basis_vector(basis_index)*Atimesv;
115 local_rows[basis_index][neighbor_ranks_.size()].push_back(entry);
120 for (std::size_t neighbor_id = 0; neighbor_id < neighbor_ranks_.size(); neighbor_id++) {
121 if (basis_index_remote >= local_basis_sizes_[neighbor_ranks_[neighbor_id]])
124 auto basis_vector = *neighbor_basis[neighbor_id];
126 native(AF_exterior_).mv(native(basis_vector), native(Atimesv));
128 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[my_rank_]; basis_index++) {
130 field_type entry = *subdomainbasis_->get_basis_vector(basis_index)*Atimesv;
131 local_rows[basis_index][neighbor_id].push_back(entry);
138 auto setup_row = coarse_system_->createbegin();
139 rank_type row_id = 0;
140 for (rank_type rank = 0; rank < ranks_; rank++) {
141 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[rank]; basis_index++) {
144 rank_type couplings = 0;
145 if (rank == my_rank_) {
146 couplings = local_basis_sizes_[my_rank_];
147 for (rank_type neighbor_id : neighbor_ranks_) {
148 couplings += local_basis_sizes_[neighbor_id];
151 gfs_.gridView().comm().broadcast(&couplings, 1, rank);
154 rank_type entries_pos[couplings];
155 if (rank == my_rank_) {
157 for (rank_type basis_index2 = 0; basis_index2 < local_basis_sizes_[my_rank_]; basis_index2++) {
158 entries_pos[cnt] = my_basis_array_offset_ + basis_index2;
161 for (std::size_t neighbor_id = 0; neighbor_id < neighbor_ranks_.size(); neighbor_id++) {
162 rank_type neighbor_offset = basis_array_offset (neighbor_ranks_[neighbor_id]);
163 for (rank_type basis_index2 = 0; basis_index2 < local_basis_sizes_[neighbor_ranks_[neighbor_id]]; basis_index2++) {
164 entries_pos[cnt] = neighbor_offset + basis_index2;
169 gfs_.gridView().comm().broadcast(entries_pos, couplings, rank);
172 field_type entries[couplings];
173 if (rank == my_rank_) {
175 for (rank_type basis_index2 = 0; basis_index2 < local_basis_sizes_[my_rank_]; basis_index2++) {
176 entries[cnt] = local_rows[basis_index][neighbor_ranks_.size()][basis_index2];
179 for (std::size_t neighbor_id = 0; neighbor_id < neighbor_ranks_.size(); neighbor_id++) {
180 for (rank_type basis_index2 = 0; basis_index2 < local_basis_sizes_[neighbor_ranks_[neighbor_id]]; basis_index2++) {
181 entries[cnt] = local_rows[basis_index][neighbor_id][basis_index2];
186 gfs_.gridView().comm().broadcast(entries, couplings, rank);
189 for (rank_type i = 0; i < couplings; i++)
190 setup_row.insert(entries_pos[i]);
194 for (rank_type i = 0; i < couplings; i++) {
195 (*coarse_system_)[row_id][entries_pos[i]] = entries[i];
203 if (my_rank_ == 0 && verbosity_ > 0) std::cout <<
"Matrix setup finished: M=" << timer_setup.
elapsed() << std::endl;
208 rank_type basis_array_offset (rank_type rank) {
209 rank_type offset = 0;
210 for (rank_type i = 0; i < rank; i++) {
211 offset += local_basis_sizes_[i];
220 using Dune::PDELab::Backend::native;
222 rank_type recvcounts[ranks_];
223 rank_type displs[ranks_];
224 for (rank_type rank = 0; rank < ranks_; rank++) {
227 for (rank_type rank = 0; rank < ranks_; rank++) {
228 recvcounts[rank] = local_basis_sizes_[rank];
229 for (rank_type i = rank+1; i < ranks_; i++)
230 displs[i] += local_basis_sizes_[rank];
233 field_type buf_defect[global_basis_size_];
234 field_type buf_defect_local[local_basis_sizes_[my_rank_]];
236 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[my_rank_]; basis_index++) {
237 buf_defect_local[basis_index] = 0.0;
238 for (std::size_t i = 0; i < native(fine).N(); i++)
239 buf_defect_local[basis_index] += native(*subdomainbasis_->get_basis_vector(basis_index))[i] * native(fine)[i];
243 for (rank_type basis_index = 0; basis_index < global_basis_size_; basis_index++) {
244 restricted[basis_index] = buf_defect[basis_index];
249 using Dune::PDELab::Backend::native;
254 for (rank_type basis_index = 0; basis_index < local_basis_sizes_[my_rank_]; basis_index++) {
255 X local_result(*subdomainbasis_->get_basis_vector(basis_index));
256 native(local_result) *= coarse[my_basis_array_offset_ + basis_index];
257 prolongated += local_result;
262 return coarse_system_;
266 return global_basis_size_;
272 const M& AF_exterior_;
276 std::vector<rank_type> neighbor_ranks_;
278 rank_type ranks_, my_rank_;
280 std::shared_ptr<SubdomainBasis<X> > subdomainbasis_;
282 std::vector<rank_type> local_basis_sizes_;
283 rank_type my_basis_array_offset_;
284 rank_type global_basis_size_;
286 std::shared_ptr<COARSE_M> coarse_system_;
Representation of a coarse space intended for two-level Schwarz preconditioners.
Definition: coarsespace.hh:8
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:466
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition: bcrsmatrix.hh:488
@ row_wise
Build in a row-wise manner.
Definition: bcrsmatrix.hh:517
A vector of blocks with memory management.
Definition: bvector.hh:392
Gather/scatter communication that passes a single function from each subdomain to all its neighbors....
Definition: multicommdatahandle.hh:189
This represents a general per-subdomain basis.
Definition: subdomainbasis.hh:12
This constructs a coarse space from a per-subdomain local basis.
Definition: subdomainprojectedcoarsespace.hh:28
void prolongate(const COARSE_V &coarse, X &prolongated) const override
Prolongates a vector defined on the coarse space to the subdomain.
Definition: subdomainprojectedcoarsespace.hh:248
rank_type basis_size() override
Returns the size of the coarse basis.
Definition: subdomainprojectedcoarsespace.hh:265
void restrict(const X &fine, COARSE_V &restricted) const override
Restricts a vector defined on a subdomain to the coarse space.
Definition: subdomainprojectedcoarsespace.hh:218
std::shared_ptr< COARSE_M > get_coarse_system() override
Returns the matrix representing the coarse basis.
Definition: subdomainprojectedcoarsespace.hh:261
SubdomainProjectedCoarseSpace(const GFS &gfs, const M &AF_exterior_, std::shared_ptr< SubdomainBasis< X > > subdomainbasis, const PIH ¶llelhelper, int verbosity=1)
Constructor.
Definition: subdomainprojectedcoarsespace.hh:42
A simple stop watch.
Definition: timer.hh:43
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:77
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Provide some classes to reduce boiler plate code in pdelab applications.
A traits class describing the mapping of types onto MPI_Datatypes.
Definition: mpitraits.hh:41