Skip to content

Commit 568c70a

Browse files
authored
Merge pull request #3298 from boutproject/hermitespline
Improvements for hermitespline interpolation
2 parents 93cc191 + 58db33a commit 568c70a

18 files changed

Lines changed: 824 additions & 394 deletions

File tree

.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ a71cad2dd6ace5741a754e2ca7daacd4bb094e0e
1111
2c2402ed59c91164eaff46dee0f79386b7347e9e
1212
05b7c571544c3bcb153fce67d12b9ac48947fc2d
1313
c8f38049359170a34c915e209276238ea66b9a1e
14+
65880e4af16cb95438437bf057c4b9fdb427b142
15+
d1cfb8abd6aa5c76e6c1a4d7ab20929c65f8afc2
1416
8d5cb39e03c2644715a50684f8cd0318b4e82676
1517
ec69e8838be2dde140a915e50506f8e1ce3cb534
1618
f2bc0488a298f136294c523bc5ab4086d090059b

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,12 @@ set(BOUT_SOURCES
296296
./src/mesh/interpolation/hermite_spline_z.cxx
297297
./src/mesh/interpolation/interpolation_z.cxx
298298
./src/mesh/interpolation/lagrange_4pt_xz.cxx
299-
./src/mesh/interpolation/monotonic_hermite_spline_xz.cxx
300299
./src/mesh/invert3x3.hxx
301300
./src/mesh/mesh.cxx
302301
./src/mesh/parallel/fci.cxx
303302
./src/mesh/parallel/fci.hxx
303+
./src/mesh/parallel/fci_comm.cxx
304+
./src/mesh/parallel/fci_comm.hxx
304305
./src/mesh/parallel/identity.cxx
305306
./src/mesh/parallel/shiftedmetric.cxx
306307
./src/mesh/parallel/shiftedmetricinterp.cxx

include/bout/interpolation_xz.hxx

Lines changed: 49 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,18 @@
2727
#include <bout/bout_types.hxx>
2828
#include <bout/generic_factory.hxx>
2929
#include <bout/mask.hxx>
30+
#include <array>
3031

31-
#define USE_NEW_WEIGHTS 1
3232
#if BOUT_HAS_PETSC
33-
#define HS_USE_PETSC 1
34-
#endif
35-
36-
#ifdef HS_USE_PETSC
3733
#include "bout/petsclib.hxx"
3834
#endif
3935

36+
namespace {
37+
enum class implementation_type { new_weights, petsc, legacy };
38+
}
39+
4040
class Options;
41+
class GlobalField3DAccess;
4142

4243
/// Interpolate a field onto a perturbed set of points
4344
const Field3D interpolate(const Field3D& f, const Field3D& delta_x,
@@ -135,14 +136,26 @@ public:
135136
}
136137
};
137138

138-
class XZHermiteSpline : public XZInterpolation {
139+
/// Monotonic Hermite spline interpolator
140+
///
141+
/// Similar to XZHermiteSpline, so uses most of the same code.
142+
/// Forces the interpolated result to be in the range of the
143+
/// neighbouring cell values. This prevents unphysical overshoots,
144+
/// but also degrades accuracy near maxima and minima.
145+
/// Perhaps should only impose near boundaries, since that is where
146+
/// problems most obviously occur.
147+
template <bool monotonic, implementation_type imp_type>
148+
class XZHermiteSplineBase : public XZInterpolation {
139149
protected:
140150
/// This is protected rather than private so that it can be
141151
/// extended and used by HermiteSplineMonotonic
142152

143153
Tensor<SpecificInd<IND_TYPE::IND_3D>> i_corner; // index of bottom-left grid point
144154
Tensor<int> k_corner; // z-index of bottom-left grid point
145155

156+
std::unique_ptr<GlobalField3DAccess> gf3daccess;
157+
Tensor<std::array<int, 4>> g3dinds;
158+
146159
// Basis functions for cubic Hermite spline interpolation
147160
// see http://en.wikipedia.org/wiki/Cubic_Hermite_spline
148161
// The h00 and h01 basis functions are applied to the function itself
@@ -160,23 +173,28 @@ protected:
160173

161174
std::vector<Field3D> newWeights;
162175

163-
#if HS_USE_PETSC
176+
#if BOUT_HAS_PETSC
164177
PetscLib* petsclib;
165178
bool isInit{false};
166-
Mat petscWeights;
167-
Vec rhs, result;
179+
Mat petscWeights{};
180+
Vec rhs{}, result{};
168181
#endif
169182

183+
/// Factors to allow for some wiggleroom
184+
BoutReal abs_fac_monotonic{1e-2};
185+
BoutReal rel_fac_monotonic{1e-1};
186+
170187
public:
171-
XZHermiteSpline(Mesh* mesh = nullptr, [[maybe_unused]] Options* options = nullptr)
172-
: XZHermiteSpline(0, mesh) {}
173-
XZHermiteSpline(int y_offset = 0, Mesh* mesh = nullptr);
174-
XZHermiteSpline(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr)
175-
: XZHermiteSpline(y_offset, mesh) {
188+
XZHermiteSplineBase(Mesh* mesh = nullptr, [[maybe_unused]] Options* options = nullptr)
189+
: XZHermiteSplineBase(0, mesh, options) {}
190+
XZHermiteSplineBase(int y_offset = 0, Mesh* mesh = nullptr, Options* options = nullptr);
191+
XZHermiteSplineBase(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr,
192+
Options* options = nullptr)
193+
: XZHermiteSplineBase(y_offset, mesh, options) {
176194
setRegion(regionFromMask(mask, localmesh));
177195
}
178-
~XZHermiteSpline() {
179-
#if HS_USE_PETSC
196+
~XZHermiteSplineBase() override {
197+
#if BOUT_HAS_PETSC
180198
if (isInit) {
181199
MatDestroy(&petscWeights);
182200
VecDestroy(&rhs);
@@ -205,61 +223,21 @@ public:
205223
getWeightsForYApproximation(int i, int j, int k, int yoffset) override;
206224
};
207225

208-
/// Monotonic Hermite spline interpolator
209-
///
210-
/// Similar to XZHermiteSpline, so uses most of the same code.
211-
/// Forces the interpolated result to be in the range of the
212-
/// neighbouring cell values. This prevents unphysical overshoots,
213-
/// but also degrades accuracy near maxima and minima.
214-
/// Perhaps should only impose near boundaries, since that is where
215-
/// problems most obviously occur.
216-
///
217-
/// You can control how tight the clipping to the range of the neighbouring cell
218-
/// values through ``rtol`` and ``atol``:
219-
///
220-
/// diff = (max_of_neighours - min_of_neighours) * rtol + atol
221-
///
222-
/// and the interpolated value is instead clipped to the range
223-
/// ``[min_of_neighours - diff, max_of_neighours + diff]``
224-
class XZMonotonicHermiteSpline : public XZHermiteSpline {
225-
/// Absolute tolerance for clipping
226-
BoutReal atol = 0.0;
227-
/// Relative tolerance for clipping
228-
BoutReal rtol = 1.0;
229-
230-
public:
231-
XZMonotonicHermiteSpline(Mesh* mesh = nullptr, Options* options = nullptr)
232-
: XZHermiteSpline(0, mesh),
233-
atol{(*options)["atol"]
234-
.doc("Absolute tolerance for clipping overshoot")
235-
.withDefault(0.0)},
236-
rtol{(*options)["rtol"]
237-
.doc("Relative tolerance for clipping overshoot")
238-
.withDefault(1.0)} {
239-
if (localmesh->getNXPE() > 1) {
240-
throw BoutException("Do not support MPI splitting in X");
241-
}
242-
}
243-
XZMonotonicHermiteSpline(int y_offset = 0, Mesh* mesh = nullptr)
244-
: XZHermiteSpline(y_offset, mesh) {
245-
if (localmesh->getNXPE() > 1) {
246-
throw BoutException("Do not support MPI splitting in X");
247-
}
248-
}
249-
XZMonotonicHermiteSpline(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr)
250-
: XZHermiteSpline(mask, y_offset, mesh) {
251-
if (localmesh->getNXPE() > 1) {
252-
throw BoutException("Do not support MPI splitting in X");
253-
}
254-
}
255-
256-
using XZHermiteSpline::interpolate;
257-
/// Interpolate using precalculated weights.
258-
/// This function is called by the other interpolate functions
259-
/// in the base class XZHermiteSpline.
260-
Field3D interpolate(const Field3D& f,
261-
const std::string& region = "RGN_NOBNDRY") const override;
262-
};
226+
using XZMonotonicHermiteSplineSerial =
227+
XZHermiteSplineBase<true, implementation_type::new_weights>;
228+
using XZHermiteSplineSerial =
229+
XZHermiteSplineBase<false, implementation_type::new_weights>;
230+
using XZMonotonicHermiteSplineLegacy =
231+
XZHermiteSplineBase<true, implementation_type::legacy>;
232+
using XZHermiteSplineLegacy = XZHermiteSplineBase<false, implementation_type::legacy>;
233+
#if BOUT_HAS_PETSC
234+
using XZMonotonicHermiteSpline = XZHermiteSplineBase<true, implementation_type::petsc>;
235+
using XZHermiteSpline = XZHermiteSplineBase<false, implementation_type::petsc>;
236+
#else
237+
using XZMonotonicHermiteSpline =
238+
XZHermiteSplineBase<true, implementation_type::new_weights>;
239+
using XZHermiteSpline = XZHermiteSplineBase<false, implementation_type::new_weights>;
240+
#endif
263241

264242
/// XZLagrange4pt interpolation class
265243
///

include/bout/mesh.hxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ public:
360360
virtual int getXProcIndex() const = 0; ///< This processor's index in X direction
361361
virtual int getYProcIndex() const = 0; ///< This processor's index in Y direction
362362
virtual int getZProcIndex() const = 0; ///< This processor's index in Z direction
363+
/// The index of a processor with given X, Y, and Z index
364+
virtual int getProcIndex(int X, int Y, int Z) const = 0;
363365

364366
// X communications
365367
virtual bool firstX()

include/bout/msg_stack.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public:
8282
}
8383

8484
void pop() {}
85-
void pop(int [[maybe_unused]] id) {}
85+
void pop([[maybe_unused]] int id) {}
8686
void clear() {}
8787

8888
void dump() {}

include/bout/region.hxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class BoutMask;
139139
BOUT_FOR_OMP(index, (region), for schedule(BOUT_OPENMP_SCHEDULE) nowait)
140140
// NOLINTEND(cppcoreguidelines-macro-usage,bugprone-macro-parentheses)
141141

142-
enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2 };
142+
enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2, IND_GLOBAL_3D = 3 };
143143

144144
/// Indices base class for Fields -- Regions are dereferenced into these
145145
///
@@ -386,6 +386,7 @@ inline SpecificInd<N> operator-(SpecificInd<N> lhs, const SpecificInd<N>& rhs) {
386386
using Ind3D = SpecificInd<IND_TYPE::IND_3D>;
387387
using Ind2D = SpecificInd<IND_TYPE::IND_2D>;
388388
using IndPerp = SpecificInd<IND_TYPE::IND_PERP>;
389+
using IndG3D = SpecificInd<IND_TYPE::IND_GLOBAL_3D>;
389390

390391
/// Get string representation of Ind3D
391392
inline std::string toString(const Ind3D& i) {

src/mesh/impls/bout/boutmesh.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@ int BoutMesh::load() {
555555
PE_XIND = MYPE % NXPE;
556556
PE_ZIND = 0;
557557

558+
ASSERT2(MYPE == getProcIndex(PE_XIND, PE_YIND, PE_ZIND));
559+
558560
// Set the other grid sizes from nx, ny, nz
559561
setDerivedGridSizes();
560562

@@ -1036,6 +1038,8 @@ void BoutMesh::createXBoundaries() {
10361038
}
10371039
}
10381040

1041+
int BoutMesh::getProcIndex(int X, int Y, int Z) const { return Y * NXPE + X; }
1042+
10391043
void BoutMesh::createYBoundaries() {
10401044
if (MYG <= 0) {
10411045
return;

src/mesh/impls/bout/boutmesh.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public:
6363
int getXProcIndex() const override; ///< This processor's index in X direction
6464
int getYProcIndex() const override; ///< This processor's index in Y direction
6565
int getZProcIndex() const override; ///< This processor's index in Z direction
66+
int getProcIndex(int X, int Y, int Z) const override;
6667

6768
/////////////////////////////////////////////
6869
// X communications

0 commit comments

Comments
 (0)