ThunderEgg  1.0.0
LinearRestrictor.h
Go to the documentation of this file.
1 /***************************************************************************
2  * ThunderEgg, a library for solvers on adaptively refined block-structured
3  * Cartesian grids.
4  *
5  * Copyright (c) 2019-2021 Scott Aiton
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  ***************************************************************************/
20 
21 #ifndef THUNDEREGG_GMG_LINEARRESTRICTOR_H
22 #define THUNDEREGG_GMG_LINEARRESTRICTOR_H
23 
29 namespace ThunderEgg::GMG {
33 template<int D>
35 {
36 private:
40  bool extrapolate_boundary_ghosts;
41 
49  void extrapolateBoundaries(const PatchInfo<D>& pinfo,
50  const PatchView<const double, D>& fine_view,
51  const PatchView<double, D>& coarse_view) const
52  {
53  Orthant<D> orth = pinfo.orth_on_parent;
54  std::array<int, D> starts;
55  for (size_t i = 0; i < D; i++) {
56  starts[i] = orth.isLowerOnAxis(i) ? 0 : coarse_view.getEnd()[i] + 1;
57  }
58  // extrapolate ghost values
59  for (Side<D> s : pinfo.orth_on_parent.getExteriorSides()) {
60  // if (!pinfo.hasNbr(s)) {
61  View<const double, D> fine_ghost = fine_view.getSliceOn(s, { -1 });
62  View<const double, D> fine_interior = fine_view.getSliceOn(s, { 0 });
63  View<double, D> coarse_ghost = coarse_view.getSliceOn(s, { -1 });
64  Loop::OverInteriorIndexes<D>(fine_ghost, [&](const std::array<int, D>& coord) {
65  std::array<int, D> coarse_coord;
66  for (size_t x = 0; x < s.getAxisIndex(); x++) {
67  coarse_coord[x] = (coord[x] + starts[x]) / 2;
68  }
69  for (size_t x = s.getAxisIndex() + 1; x < D; x++) {
70  coarse_coord[x - 1] = (coord[x - 1] + starts[x]) / 2;
71  }
72  coarse_coord[D - 1] = coord[D - 1];
73  coarse_ghost[coarse_coord] += (3 * fine_ghost[coord] - fine_interior[coord]) / (1 << D);
74  });
75  //}
76  }
77  if constexpr (D >= 2) {
78  Corner<D> c(pinfo.orth_on_parent.getIndex());
79  if (!pinfo.hasNbr(c)) {
80  std::array<int, D> neg_one;
81  neg_one.fill(-1);
82  std::array<int, D> zero;
83  zero.fill(0);
84  View<const double, 1> fine_ghost = fine_view.getSliceOn(c, neg_one);
85  View<const double, 1> fine_interior = fine_view.getSliceOn(c, zero);
86  View<double, 1> coarse_ghost = coarse_view.getSliceOn(c, neg_one);
87  Loop::OverInteriorIndexes<1>(fine_ghost, [&](const std::array<int, 1>& coord) {
88  coarse_ghost[coord] += (3 * fine_ghost[coord] - fine_interior[coord]);
89  });
90  }
91  }
92  }
101  void restrictToCoarserParent(const PatchInfo<D>& pinfo,
102  int parent_index,
103  const Vector<D>& finer_vector,
104  Vector<D>& coarser_vector) const
105  {
106  PatchView<double, D> coarse_view = coarser_vector.getPatchView(parent_index);
107  PatchView<const double, D> fine_view = finer_vector.getPatchView(pinfo.local_index);
108  // get starting index in coarser patch
109  Orthant<D> orth = pinfo.orth_on_parent;
110  std::array<int, D> starts;
111  for (size_t i = 0; i < D; i++) {
112  starts[i] = orth.isLowerOnAxis(i) ? 0 : (coarse_view.getEnd()[i] + 1);
113  }
114 
115  // interpolate interior values
116  Loop::OverInteriorIndexes<D + 1>(fine_view, [&](const std::array<int, D + 1>& coord) {
117  std::array<int, D + 1> coarse_coord;
118  for (size_t x = 0; x < D; x++) {
119  coarse_coord[x] = (coord[x] + starts[x]) / 2;
120  }
121  coarse_coord[D] = coord[D];
122  coarse_view[coarse_coord] += fine_view[coord] / (1 << D);
123  });
124 
125  if (extrapolate_boundary_ghosts) {
126  extrapolateBoundaries(pinfo, fine_view, coarse_view);
127  }
128  }
138  void copyToParent(const PatchInfo<D>& pinfo,
139  int parent_index,
140  const Vector<D>& finer_vector,
141  Vector<D>& coarser_vector) const
142  {
143  PatchView<double, D> coarse_view = coarser_vector.getPatchView(parent_index);
144  PatchView<const double, D> fine_view = finer_vector.getPatchView(pinfo.local_index);
145  // just copy the values
146  if (extrapolate_boundary_ghosts) {
147  Loop::OverAllIndexes<D + 1>(fine_view, [&](const std::array<int, D + 1>& coord) {
148  coarse_view[coord] += fine_view[coord];
149  });
150  } else {
151  Loop::OverInteriorIndexes<D + 1>(fine_view, [&](const std::array<int, D + 1>& coord) {
152  coarse_view[coord] += fine_view[coord];
153  });
154  }
155  }
156 
157 public:
166  LinearRestrictor(const Domain<D>& fine_domain,
167  const Domain<D>& coarse_domain,
168  bool extrapolate_boundary_ghosts = false)
169  : MPIRestrictor<D>(coarse_domain, fine_domain)
170  , extrapolate_boundary_ghosts(extrapolate_boundary_ghosts)
171  {}
172 
178  LinearRestrictor<D>* clone() const override { return new LinearRestrictor<D>(*this); }
180  const std::vector<std::pair<int, std::reference_wrapper<const PatchInfo<D>>>>& patches,
181  const Vector<D>& finer_vector,
182  Vector<D>& coarser_vector) const override
183  {
184  for (const auto& pair : patches) {
185  if (pair.second.get().hasCoarseParent()) {
186  restrictToCoarserParent(pair.second.get(), pair.first, finer_vector, coarser_vector);
187  } else {
188  copyToParent(pair.second.get(), pair.first, finer_vector, coarser_vector);
189  }
190  }
191  }
192 };
193 } // namespace ThunderEgg::GMG
194 // explicit instantiation
195 extern template class ThunderEgg::GMG::LinearRestrictor<2>;
196 extern template class ThunderEgg::GMG::LinearRestrictor<3>;
197 #endif
ThunderEgg::View
Array for acessing data of a patch. It supports variable striding.
Definition: View.h:40
ThunderEgg::Orthant
An enum-style class that represents the octants of a cube.
Definition: Orthant.h:43
ThunderEgg::PatchInfo::orth_on_parent
Orthant< D > orth_on_parent
The orthant of the parent that this parent resides on.
Definition: PatchInfo.h:113
ThunderEgg::PatchInfo::hasNbr
bool hasNbr(Face< D, M > s) const
Return whether the patch has a neighbor.
Definition: PatchInfo.h:284
ThunderEgg::GMG::LinearRestrictor::clone
LinearRestrictor< D > * clone() const override
Clone this restrictor.
Definition: LinearRestrictor.h:178
ThunderEgg::PatchView::getSliceOn
View< T, M+1 > getSliceOn(Face< D, M > f, const std::array< int, D - M > &offset) const
Get the slice on a given face.
Definition: PatchView.h:200
ThunderEgg::Domain
Uses a collection of PatchInfo objects to represent the domain of the problem.
Definition: Domain.h:50
ThunderEgg::GMG::LinearRestrictor::restrictPatches
void restrictPatches(const std::vector< std::pair< int, std::reference_wrapper< const PatchInfo< D >>>> &patches, const Vector< D > &finer_vector, Vector< D > &coarser_vector) const override
Restrict values into coarse vector.
Definition: LinearRestrictor.h:179
ThunderEgg::PatchInfo::local_index
int local_index
The local index of the patch in the Domain.
Definition: PatchInfo.h:69
MPIRestrictor.h
MPIRestrictor class.
ThunderEgg::PatchView
View for accessing data of a patch. It supports variable striding.
Definition: PatchView.h:37
ThunderEgg::GMG::MPIRestrictor
Base class that makes the necessary mpi calls, derived classes only have to implement restrictPatches...
Definition: MPIRestrictor.h:38
ThunderEgg::GMG::LinearRestrictor::LinearRestrictor
LinearRestrictor(const Domain< D > &fine_domain, const Domain< D > &coarse_domain, bool extrapolate_boundary_ghosts=false)
Create new LinearRestrictor object.
Definition: LinearRestrictor.h:166
ThunderEgg::View::getEnd
const std::array< int, D > & getEnd() const
Get the coordinate of the last element.
Definition: View.h:211
ThunderEgg::PatchInfo
Contains metadata for a patch.
Definition: PatchInfo.h:51
ThunderEgg::Vector::getPatchView
PatchView< double, D > getPatchView(int patch_local_index)
Get the View objects for the specified patch index of View object will correspond to component index.
Definition: Vector.h:358
ThunderEgg::Vector
Vector class for use in thunderegg.
Definition: Vector.h:42
ThunderEgg::Face
Enum-style class for the faces of an n-dimensional cube.
Definition: Face.h:41
ThunderEgg::GMG::LinearRestrictor
Restrictor that averages the corresponding fine cells into each coarse cell.
Definition: LinearRestrictor.h:34
ThunderEgg::GMG
Geometric-Multigrid classes.
Definition: Cycle.h:33