ThunderEgg  1.0.0
StarPatchOperator.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_VARPOISSON_STARPATCHOPERATOR_H
22 #define THUNDEREGG_VARPOISSON_STARPATCHOPERATOR_H
23 
29 #include <ThunderEgg/DomainTools.h>
30 #include <ThunderEgg/GMG/Level.h>
31 #include <ThunderEgg/GhostFiller.h>
34 #include <ThunderEgg/Vector.h>
35 
36 namespace ThunderEgg {
37 namespace VarPoisson {
45 template<int D>
47 {
48 protected:
49  Vector<D> coeffs;
50 
51  constexpr int addValue(int axis) const { return (axis == 0) ? 0 : 1; }
52 
53 public:
62  const Domain<D>& domain,
63  const GhostFiller<D>& ghost_filler)
64  : PatchOperator<D>(domain, ghost_filler)
65  , coeffs(coeffs)
66  {
67  if (domain.getNumGhostCells() < 1) {
68  throw RuntimeError("StarPatchOperator needs at least one set of ghost cells");
69  }
70  ghost_filler.fillGhost(this->coeffs);
71  }
77  StarPatchOperator<D>* clone() const override { return new StarPatchOperator<D>(*this); }
78  void applySinglePatch(const PatchInfo<D>& pinfo,
79  const PatchView<const double, D>& u_view,
80  const PatchView<double, D>& f_view,
81  bool interior) const
82  {
83  if (interior) {
84  enforceInternalBoundaryConditions(pinfo, u_view);
85  }
86  enforceBoundaryConditions(pinfo, u_view);
87 
89  std::array<double, D> h2 = pinfo.spacings;
90  for (size_t i = 0; i < D; i++) {
91  h2[i] *= h2[i];
92  }
93  Loop::Unroll<0, D - 1>([&](int axis) {
94  int stride = u_view.getStrides()[axis];
95  int c_stride = c.getStrides()[axis];
96  Loop::OverInteriorIndexes<D + 1>(u_view, [&](std::array<int, D + 1> coord) {
97  const double* ptr = &u_view[coord];
98  const double* c_ptr = &c[coord];
99  double lower = *(ptr - stride);
100  double mid = *ptr;
101  double upper = *(ptr + stride);
102  double c_lower = *(c_ptr - c_stride);
103  double c_mid = *c_ptr;
104  double c_upper = *(c_ptr + c_stride);
105  f_view[coord] =
106  addValue(axis) * f_view[coord] +
107  ((c_upper + c_mid) * (upper - mid) - (c_lower + c_mid) * (mid - lower)) / (2 * h2[axis]);
108  });
109  });
110  }
111 
112  void applySinglePatch(const PatchInfo<D>& pinfo,
113  const PatchView<const double, D>& u_view,
114  const PatchView<double, D>& f_view) const override
115  {
116  applySinglePatch(pinfo, u_view, f_view, false);
117  }
119  const PatchInfo<D>& pinfo,
120  const PatchView<const double, D>& u_view,
121  const PatchView<double, D>& f_view) const override
122  {
123  applySinglePatch(pinfo, u_view, f_view, true);
124  }
125 
126  void enforceBoundaryConditions(const PatchInfo<D>& pinfo,
127  const PatchView<const double, D>& u_view) const
128  {
129  for (int axis = 0; axis < D; axis++) {
130  Side<D> lower_side(axis * 2);
131  Side<D> upper_side(axis * 2 + 1);
132  if (!pinfo.hasNbr(lower_side)) {
133  View<double, D> lower = u_view.getGhostSliceOn(lower_side, { 0 });
134  View<const double, D> mid = u_view.getSliceOn(lower_side, { 0 });
135  Loop::OverInteriorIndexes<D>(mid,
136  [&](std::array<int, D> coord) { lower[coord] = -mid[coord]; });
137  }
138  if (!pinfo.hasNbr(upper_side)) {
139  View<double, D> upper = u_view.getGhostSliceOn(upper_side, { 0 });
140  View<const double, D> mid = u_view.getSliceOn(upper_side, { 0 });
141  Loop::OverInteriorIndexes<D>(mid,
142  [&](std::array<int, D> coord) { upper[coord] = -mid[coord]; });
143  }
144  }
145  }
146 
147  void enforceInternalBoundaryConditions(const PatchInfo<D>& pinfo,
148  const PatchView<const double, D>& u_view) const
149  {
150  for (int axis = 0; axis < D; axis++) {
151  Side<D> lower_side(axis * 2);
152  Side<D> upper_side(axis * 2 + 1);
153  if (pinfo.hasNbr(lower_side)) {
154  View<double, D> lower = u_view.getGhostSliceOn(lower_side, { 0 });
155  View<const double, D> mid = u_view.getSliceOn(lower_side, { 0 });
156  Loop::OverInteriorIndexes<D>(mid,
157  [&](std::array<int, D> coord) { lower[coord] = -mid[coord]; });
158  }
159  if (pinfo.hasNbr(upper_side)) {
160  View<double, D> upper = u_view.getGhostSliceOn(upper_side, { 0 });
161  View<const double, D> mid = u_view.getSliceOn(upper_side, { 0 });
162  Loop::OverInteriorIndexes<D>(mid,
163  [&](std::array<int, D> coord) { upper[coord] = -mid[coord]; });
164  }
165  }
166  }
167 
169  const PatchView<const double, D>& u_view,
170  const PatchView<double, D>& f_view) const override
171  {
173  for (Side<D> s : Side<D>::getValues()) {
174  if (pinfo.hasNbr(s)) {
175  double h2 = pow(pinfo.spacings[s.getAxisIndex()], 2);
176  View<double, D> fner = f_view.getSliceOn(s, { 0 });
177  View<double, D> u_ghost = u_view.getGhostSliceOn(s, { 0 });
178  View<const double, D> uner = u_view.getSliceOn(s, { 0 });
179  View<const double, D> c_ghost = c.getSliceOn(s, { -1 });
180  View<const double, D> cner = c.getSliceOn(s, { 0 });
181  Loop::OverInteriorIndexes<D>(fner, [&](const std::array<int, D>& coord) {
182  fner[coord] -= (u_ghost[coord] + uner[coord]) * (cner[coord] + c_ghost[coord]) / (2 * h2);
183  });
184  }
185  }
186  }
195  std::function<double(const std::array<double, D>&)> gfunc,
196  std::function<double(const std::array<double, D>&)> hfunc)
197  {
198  for (int i = 0; i < f.getNumLocalPatches(); i++) {
200  auto pinfo = this->getDomain().getPatchInfoVector()[i];
201  for (Side<D> s : Side<D>::getValues()) {
202  if (!pinfo.hasNbr(s)) {
203  double h2 = pow(pinfo.spacings[s.getAxisIndex()], 2);
204  View<double, D - 1> ld = f_ld.getSliceOn(s, { 0 });
205  Loop::Nested<D - 1>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D - 1>& coord) {
206  std::array<double, D> real_coord;
207  DomainTools::GetRealCoordBound<D>(pinfo, coord, s, real_coord);
208  std::array<double, D> other_real_coord = real_coord;
209  if (s.isLowerOnAxis()) {
210  other_real_coord[s.getAxisIndex()] -= pinfo.spacings[s.getAxisIndex()];
211  } else {
212  other_real_coord[s.getAxisIndex()] += pinfo.spacings[s.getAxisIndex()];
213  }
214  ld[coord] -= 2 * gfunc(real_coord) * hfunc(real_coord) / h2;
215  });
216  }
217  }
218  }
219  }
220 };
221 extern template class StarPatchOperator<2>;
222 extern template class StarPatchOperator<3>;
223 
224 } // namespace VarPoisson
225 } // namespace ThunderEgg
226 #endif
ThunderEgg::Vector::getComponentView
ComponentView< double, D > getComponentView(int component_index, int patch_local_index)
Get the ComponentView for the specified patch and component.
Definition: Vector.h:336
RuntimeError.h
RuntimeError struct.
ThunderEgg::Loop::Nested
static void Nested(A start, A end, T lambda)
Loop over a range of integer coordinates.
Definition: Loops.h:125
ThunderEgg::View< double, D >
ThunderEgg::Loop::Unroll
static void Unroll(T lambda)
Unroll a fixed-length loop.
Definition: Loops.h:72
Vector.h
Vector class.
ThunderEgg::View< T, D+1 >::getStrides
const std::array< int, D > & getStrides() const
Get the strides of the patch in each direction.
Definition: View.h:203
ThunderEgg::PatchInfo::hasNbr
bool hasNbr(Face< D, M > s) const
Return whether the patch has a neighbor.
Definition: PatchInfo.h:284
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::PatchView::getGhostSliceOn
View< typename std::remove_const< T >::type, M+1 > getGhostSliceOn(Face< D, M > f, const std::array< size_t, D - M > &offset) const
Get the gosts slice on a given face.
Definition: PatchView.h:219
ThunderEgg::GhostFiller::fillGhost
virtual void fillGhost(const Vector< D > &u) const =0
Fill ghost cells on a vector.
ThunderEgg::VarPoisson::StarPatchOperator::clone
StarPatchOperator< D > * clone() const override
Get a clone of this operator.
Definition: StarPatchOperator.h:77
DomainTools.h
DomainTools class.
ThunderEgg::ComponentView< double, D >
ThunderEgg::VarPoisson::StarPatchOperator
Implements a variable coefficient Laplacian f=Div[h*Grad[u]].
Definition: StarPatchOperator.h:46
ThunderEgg::Domain
Uses a collection of PatchInfo objects to represent the domain of the problem.
Definition: Domain.h:50
PatchOperator.h
PatchOperator class.
ThunderEgg::PatchInfo::local_index
int local_index
The local index of the patch in the Domain.
Definition: PatchInfo.h:69
Level.h
Level class.
ThunderEgg::ComponentView::getSliceOn
View< T, M > getSliceOn(Face< D, M > f, const std::array< int, D - M > &offset) const
Get the slice on a given face.
Definition: ComponentView.h:194
ThunderEgg::VarPoisson::StarPatchOperator::StarPatchOperator
StarPatchOperator(const Vector< D > &coeffs, const Domain< D > &domain, const GhostFiller< D > &ghost_filler)
Construct a new StarPatchOperator object.
Definition: StarPatchOperator.h:61
ThunderEgg::PatchView
View for accessing data of a patch. It supports variable striding.
Definition: PatchView.h:37
ThunderEgg
The ThunderEgg namespace.
Definition: BiLinearGhostFiller.h:31
GhostFiller.h
GhostFiller class.
ThunderEgg::VarPoisson::StarPatchOperator::applySinglePatch
void applySinglePatch(const PatchInfo< D > &pinfo, const PatchView< const double, D > &u_view, const PatchView< double, D > &f_view) const override
Apply the operator to a single patch.
Definition: StarPatchOperator.h:112
ThunderEgg::GhostFiller
Fills ghost cells on patches.
Definition: GhostFiller.h:36
ThunderEgg::PatchInfo
Contains metadata for a patch.
Definition: PatchInfo.h:51
ThunderEgg::Domain::getNumGhostCells
int getNumGhostCells() const
get the number of ghost cell on each side of a patch
Definition: Domain.h:295
ThunderEgg::PatchOperator::getDomain
const Domain< D > & getDomain() const
Get the Domain object associated with this PatchOperator.
Definition: PatchOperator.h:147
ThunderEgg::VarPoisson::StarPatchOperator::applySinglePatchWithInternalBoundaryConditions
void applySinglePatchWithInternalBoundaryConditions(const PatchInfo< D > &pinfo, const PatchView< const double, D > &u_view, const PatchView< double, D > &f_view) const override
Apply the operator to a single patch.
Definition: StarPatchOperator.h:118
ThunderEgg::PatchOperator
This is an Operator where derived classes only have to implement the two virtual functions that opera...
Definition: PatchOperator.h:40
ThunderEgg::PatchInfo::spacings
std::array< double, D > spacings
The cell spacings in each direction.
Definition: PatchInfo.h:125
ThunderEgg::VarPoisson::StarPatchOperator::modifyRHSForInternalBoundaryConditions
void modifyRHSForInternalBoundaryConditions(const PatchInfo< D > &pinfo, const PatchView< const double, D > &u_view, const PatchView< double, D > &f_view) const override
Treat the internal patch boundaries as domain boundaires and modify RHS accordingly.
Definition: StarPatchOperator.h:168
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::Vector::getNumLocalPatches
int getNumLocalPatches() const
Get the number of local patches.
Definition: Vector.h:316
ThunderEgg::VarPoisson::StarPatchOperator::addDrichletBCToRHS
void addDrichletBCToRHS(Vector< D > &f, std::function< double(const std::array< double, D > &)> gfunc, std::function< double(const std::array< double, D > &)> hfunc)
Helper function for adding Dirichlet boundary conditions to right hand side.
Definition: StarPatchOperator.h:194
ThunderEgg::RuntimeError
ThunderEgg runtime exception.
Definition: RuntimeError.h:36