21 #ifndef THUNDEREGG_POISSON_STARPATCHOPERATOR_H
22 #define THUNDEREGG_POISSON_STARPATCHOPERATOR_H
48 constexpr
int addValue(
int axis)
const {
return (axis == 0) ? 0 : 1; }
65 if (this->
getDomain().getNumGhostCells() < 1) {
66 throw RuntimeError(
"StarPatchOperator needs at least one set of ghost cells");
81 enforceInternalBoundaryConditions(pinfo, u_view);
84 enforceBoundaryConditions(pinfo, u_view);
86 std::array<double, D> h2 = pinfo.
spacings;
87 for (
size_t i = 0; i < D; i++) {
93 Loop::OverInteriorIndexes<D + 1>(u_view, [&](std::array<int, D + 1> coord) {
94 const double* ptr = &u_view[coord];
95 double lower = *(ptr - stride);
97 double upper = *(ptr + stride);
98 f_view[coord] = addValue(axis) * f_view[coord] + (upper - 2 * mid + lower) / h2[axis];
106 applySinglePatch(pinfo, u_view, f_view,
false);
113 applySinglePatch(pinfo, u_view, f_view,
true);
115 void enforceBoundaryConditions(
const PatchInfo<D>& pinfo,
118 for (
int axis = 0; axis < D; axis++) {
119 Side<D> lower_side = LowerSideOnAxis<D>(axis);
120 Side<D> upper_side = HigherSideOnAxis<D>(axis);
121 if (!pinfo.
hasNbr(lower_side)) {
125 Loop::OverInteriorIndexes<D>(
126 lower_mid, [&](std::array<int, D> coord) { lower[coord] = lower_mid[coord]; });
128 Loop::OverInteriorIndexes<D>(
129 lower_mid, [&](std::array<int, D> coord) { lower[coord] = -lower_mid[coord]; });
132 if (!pinfo.
hasNbr(upper_side)) {
134 View<const double, D> upper_mid = u_view.
getSliceOn(upper_side, { 0 });
136 Loop::OverInteriorIndexes<D>(
137 upper_mid, [&](std::array<int, D> coord) { upper[coord] = upper_mid[coord]; });
139 Loop::OverInteriorIndexes<D>(
140 upper_mid, [&](std::array<int, D> coord) { upper[coord] = -upper_mid[coord]; });
145 void enforceInternalBoundaryConditions(
const PatchInfo<D>& pinfo,
146 const PatchView<const double, D>& u_view)
const
148 for (
int axis = 0; axis < D; axis++) {
149 Side<D> lower_side = LowerSideOnAxis<D>(axis);
150 Side<D> upper_side = HigherSideOnAxis<D>(axis);
151 if (pinfo.hasNbr(lower_side)) {
152 View<double, D> lower = u_view.getGhostSliceOn(lower_side, { 0 });
153 View<const double, D> lower_mid = u_view.getSliceOn(lower_side, { 0 });
154 Loop::OverInteriorIndexes<D>(
155 lower_mid, [&](std::array<int, D> coord) { lower[coord] = -lower_mid[coord]; });
157 if (pinfo.hasNbr(upper_side)) {
158 View<double, D> upper = u_view.getGhostSliceOn(upper_side, { 0 });
159 View<const double, D> upper_mid = u_view.getSliceOn(upper_side, { 0 });
160 Loop::OverInteriorIndexes<D>(
161 upper_mid, [&](std::array<int, D> coord) { upper[coord] = -upper_mid[coord]; });
171 double h2 = pow(pinfo.
spacings[s.getAxisIndex()], 2);
175 Loop::OverInteriorIndexes<D>(f_inner, [&](
const std::array<int, D>& coord) {
176 f_inner[coord] -= (u_ghost[coord] + u_inner[coord]) / h2;
191 auto pinfo = this->
getDomain().getPatchInfoVector()[i];
193 if (!pinfo.hasNbr(s)) {
194 double h2 = pow(pinfo.spacings[s.getAxisIndex()], 2);
196 Loop::Nested<D - 1>(ld.getStart(), ld.getEnd(), [&](
const std::array<int, D - 1>& coord) {
197 std::array<double, D> real_coord;
198 DomainTools::GetRealCoordBound<D>(pinfo, coord, s, real_coord);
199 ld[coord] += -2.0 * gfunc(real_coord) / h2;
214 std::function<
double(
const std::array<double, D>&)> gfunc,
215 std::array<std::function<
double(
const std::array<double, D>&)>, D> gfunc_grad)
219 auto pinfo = this->
getDomain().getPatchInfoVector()[i];
221 if (!pinfo.hasNbr(s)) {
222 double h = pinfo.spacings[s.getAxisIndex()];
224 if (s.isLowerOnAxis()) {
226 ld.getStart(), ld.getEnd(), [&](
const std::array<int, D - 1>& coord) {
227 std::array<double, D> real_coord;
228 DomainTools::GetRealCoordBound<D>(pinfo, coord, s, real_coord);
229 ld[coord] += gfunc_grad[s.getAxisIndex()](real_coord) / h;
233 ld.getStart(), ld.getEnd(), [&](
const std::array<int, D - 1>& coord) {
234 std::array<double, D> real_coord;
235 DomainTools::GetRealCoordBound<D>(pinfo, coord, s, real_coord);
236 ld[coord] -= gfunc_grad[s.getAxisIndex()](real_coord) / h;
244 extern template class StarPatchOperator<2>;
245 extern template class StarPatchOperator<3>;