2424#ifndef BOUT_INTERP_XZ_H
2525#define BOUT_INTERP_XZ_H
2626
27+ #include " bout/bout_types.hxx"
2728#include " bout/mask.hxx"
2829
2930#define USE_NEW_WEIGHTS 1
@@ -166,7 +167,8 @@ protected:
166167#endif
167168
168169public:
169- XZHermiteSpline (Mesh* mesh = nullptr ) : XZHermiteSpline(0 , mesh) {}
170+ XZHermiteSpline (Mesh* mesh = nullptr , [[maybe_unused]] Options* options = nullptr )
171+ : XZHermiteSpline(0 , mesh) {}
170172 XZHermiteSpline (int y_offset = 0 , Mesh* mesh = nullptr );
171173 XZHermiteSpline (const BoutMask& mask, int y_offset = 0 , Mesh* mesh = nullptr )
172174 : XZHermiteSpline(y_offset, mesh) {
@@ -210,9 +212,29 @@ public:
210212// / but also degrades accuracy near maxima and minima.
211213// / Perhaps should only impose near boundaries, since that is where
212214// / problems most obviously occur.
215+ // /
216+ // / You can control how tight the clipping to the range of the neighbouring cell
217+ // / values through ``rtol`` and ``atol``:
218+ // /
219+ // / diff = (max_of_neighours - min_of_neighours) * rtol + atol
220+ // /
221+ // / and the interpolated value is instead clipped to the range
222+ // / ``[min_of_neighours - diff, max_of_neighours + diff]``
213223class XZMonotonicHermiteSpline : public XZHermiteSpline {
224+ // / Absolute tolerance for clipping
225+ BoutReal atol = 0.0 ;
226+ // / Relative tolerance for clipping
227+ BoutReal rtol = 1.0 ;
228+
214229public:
215- XZMonotonicHermiteSpline (Mesh* mesh = nullptr ) : XZHermiteSpline(0 , mesh) {
230+ XZMonotonicHermiteSpline (Mesh* mesh = nullptr , Options* options = nullptr )
231+ : XZHermiteSpline(0 , mesh),
232+ atol{(*options)[" atol" ]
233+ .doc (" Absolute tolerance for clipping overshoot" )
234+ .withDefault (0.0 )},
235+ rtol{(*options)[" rtol" ]
236+ .doc (" Relative tolerance for clipping overshoot" )
237+ .withDefault (1.0 )} {
216238 if (localmesh->getNXPE () > 1 ) {
217239 throw BoutException (" Do not support MPI splitting in X" );
218240 }
@@ -245,7 +267,8 @@ class XZLagrange4pt : public XZInterpolation {
245267 Field3D t_x, t_z;
246268
247269public:
248- XZLagrange4pt (Mesh* mesh = nullptr ) : XZLagrange4pt(0 , mesh) {}
270+ XZLagrange4pt (Mesh* mesh = nullptr , [[maybe_unused]] Options* options = nullptr )
271+ : XZLagrange4pt(0 , mesh) {}
249272 XZLagrange4pt (int y_offset = 0 , Mesh* mesh = nullptr );
250273 XZLagrange4pt (const BoutMask& mask, int y_offset = 0 , Mesh* mesh = nullptr )
251274 : XZLagrange4pt(y_offset, mesh) {
@@ -278,7 +301,8 @@ class XZBilinear : public XZInterpolation {
278301 Field3D w0, w1, w2, w3;
279302
280303public:
281- XZBilinear (Mesh* mesh = nullptr ) : XZBilinear(0 , mesh) {}
304+ XZBilinear (Mesh* mesh = nullptr , [[maybe_unused]] Options* options = nullptr )
305+ : XZBilinear(0 , mesh) {}
282306 XZBilinear (int y_offset = 0 , Mesh* mesh = nullptr );
283307 XZBilinear (const BoutMask& mask, int y_offset = 0 , Mesh* mesh = nullptr )
284308 : XZBilinear(y_offset, mesh) {
@@ -302,18 +326,18 @@ public:
302326};
303327
304328class XZInterpolationFactory
305- : public Factory<XZInterpolation, XZInterpolationFactory, Mesh*> {
329+ : public Factory<XZInterpolation, XZInterpolationFactory, Mesh*, Options* > {
306330public:
307331 static constexpr auto type_name = " XZInterpolation" ;
308332 static constexpr auto section_name = " xzinterpolation" ;
309333 static constexpr auto option_name = " type" ;
310334 static constexpr auto default_type = " hermitespline" ;
311335
312336 ReturnType create (Options* options = nullptr , Mesh* mesh = nullptr ) const {
313- return Factory::create (getType (options), mesh);
337+ return Factory::create (getType (options), mesh, options );
314338 }
315- ReturnType create (const std::string& type, [[maybe_unused]] Options* options) const {
316- return Factory::create (type, nullptr );
339+ ReturnType create (const std::string& type, Options* options) const {
340+ return Factory::create (type, nullptr , options );
317341 }
318342
319343 static void ensureRegistered ();
0 commit comments