From 3bda3dc2ad2abb01ce9f0a12b524274434b5effa Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 17 Jul 2018 12:08:49 +0100 Subject: [PATCH 1/8] Remove result_fa from interp_to Remove the intermediate variable result_fa in branch of interp_to that transforms to field-aligned variables. Just store the intermediate result in 'result' instead, to save memory. --- src/mesh/interpolation.cxx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mesh/interpolation.cxx b/src/mesh/interpolation.cxx index b3b9285811..fde1497f7d 100644 --- a/src/mesh/interpolation.cxx +++ b/src/mesh/interpolation.cxx @@ -151,11 +151,9 @@ const Field3D interp_to(const Field3D &var, CELL_LOC loc, REGION region) { // coordinates Field3D var_fa = fieldmesh->toFieldAligned(var); - Field3D result_fa(fieldmesh); if (region != RGN_NOBNDRY) { - result_fa = fieldmesh->toFieldAligned(result); + result = fieldmesh->toFieldAligned(result); } - result_fa.allocate(); if (fieldmesh->ystart > 1) { // More than one guard cell, so set pp and mm values @@ -180,7 +178,7 @@ const Field3D interp_to(const Field3D &var, CELL_LOC loc, REGION region) { s.m = s.c; } - result_fa[i] = interp(s); + result[i] = interp(s); } } } else { @@ -206,12 +204,12 @@ const Field3D interp_to(const Field3D &var, CELL_LOC loc, REGION region) { s.m = s.c; } - result_fa[i] = interp(s); + result[i] = interp(s); } } } - result = fieldmesh->fromFieldAligned(result_fa); + result = fieldmesh->fromFieldAligned(result); } break; } From d9d0857faabb6c2e94c54c0d08dce49522769c4b Mon Sep 17 00:00:00 2001 From: John Omotani Date: Wed, 23 May 2018 18:00:11 +0100 Subject: [PATCH 2/8] Make a method to clean up deleting yup/ydown and field_fa members --- include/field3d.hxx | 5 ++++ src/field/field3d.cxx | 36 ++++++++++++++++---------- src/field/gen_fieldops.jinja | 5 ++++ src/field/generated_fieldops.cxx | 44 ++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/include/field3d.hxx b/include/field3d.hxx index e9f090bea6..8d4ad7f9ec 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -223,6 +223,11 @@ class Field3D : public Field, public FieldData { * Ensure that yup and ydown refer to this field */ void mergeYupYdown(); + + /*! + * Delete all yup/ydown fields and field_fa + */ + void deleteYupYdown(); /// Check if this field has yup and ydown fields bool hasYupYdown() const { diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 7d9dda7cea..eb117cf734 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -146,12 +146,8 @@ Field3D::~Field3D() { // Now delete them as part of the deriv vector delete deriv; } - - if((yup_field != this) && (yup_field != nullptr)) - delete yup_field; - - if((ydown_field != this) && (ydown_field != nullptr)) - delete ydown_field; + + deleteYupYdown(); } void Field3D::allocate() { @@ -195,18 +191,25 @@ void Field3D::mergeYupYdown() { if(yup_field == this && ydown_field == this) return; - if(yup_field != nullptr){ - delete yup_field; - } - - if(ydown_field != nullptr) { - delete ydown_field; - } + deleteYupYdown(); yup_field = this; ydown_field = this; } +void Field3D::deleteYupYdown() { + // Delete auxiliary fields if they have been set + if (yup_field == this && ydown_field == this) { + return; + } + + delete yup_field; + yup_field = nullptr; + + delete ydown_field; + ydown_field = nullptr; +} + Field3D& Field3D::ynext(int dir) { switch(dir) { case +1: @@ -307,6 +310,7 @@ Field3D & Field3D::operator=(const Field3D &rhs) { setLocation(rhs.location); + deleteYupYdown(); return *this; } @@ -328,7 +332,9 @@ Field3D & Field3D::operator=(const Field2D &rhs) { /// Only 3D fields have locations for now //location = CELL_CENTRE; - + + deleteYupYdown(); + return *this; } @@ -366,6 +372,8 @@ Field3D & Field3D::operator=(const BoutReal val) { //location = CELL_CENTRE; // DON'T RE-SET LOCATION + deleteYupYdown(); + return *this; } diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index af3c3afb90..d33def747e 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -95,6 +95,11 @@ } else { (*this) = (*this) {{operator}} {{rhs.name}}; } + + {% if (out == "Field3D") %} + deleteYupYdown(); + {% endif %} + return *this; } {% endif %} diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 0456dbef1f..02c9151322 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -62,6 +62,9 @@ Field3D &Field3D::operator*=(const Field3D &rhs) { } else { (*this) = (*this) * rhs; } + + deleteYupYdown(); + return *this; } @@ -121,6 +124,9 @@ Field3D &Field3D::operator/=(const Field3D &rhs) { } else { (*this) = (*this) / rhs; } + + deleteYupYdown(); + return *this; } @@ -180,6 +186,9 @@ Field3D &Field3D::operator+=(const Field3D &rhs) { } else { (*this) = (*this) + rhs; } + + deleteYupYdown(); + return *this; } @@ -239,6 +248,9 @@ Field3D &Field3D::operator-=(const Field3D &rhs) { } else { (*this) = (*this) - rhs; } + + deleteYupYdown(); + return *this; } @@ -306,6 +318,9 @@ Field3D &Field3D::operator*=(const Field2D &rhs) { } else { (*this) = (*this) * rhs; } + + deleteYupYdown(); + return *this; } @@ -375,6 +390,9 @@ Field3D &Field3D::operator/=(const Field2D &rhs) { } else { (*this) = (*this) / rhs; } + + deleteYupYdown(); + return *this; } @@ -442,6 +460,9 @@ Field3D &Field3D::operator+=(const Field2D &rhs) { } else { (*this) = (*this) + rhs; } + + deleteYupYdown(); + return *this; } @@ -509,6 +530,9 @@ Field3D &Field3D::operator-=(const Field2D &rhs) { } else { (*this) = (*this) - rhs; } + + deleteYupYdown(); + return *this; } @@ -546,6 +570,9 @@ Field3D &Field3D::operator*=(const BoutReal rhs) { } else { (*this) = (*this) * rhs; } + + deleteYupYdown(); + return *this; } @@ -583,6 +610,9 @@ Field3D &Field3D::operator/=(const BoutReal rhs) { } else { (*this) = (*this) / rhs; } + + deleteYupYdown(); + return *this; } @@ -620,6 +650,9 @@ Field3D &Field3D::operator+=(const BoutReal rhs) { } else { (*this) = (*this) + rhs; } + + deleteYupYdown(); + return *this; } @@ -657,6 +690,9 @@ Field3D &Field3D::operator-=(const BoutReal rhs) { } else { (*this) = (*this) - rhs; } + + deleteYupYdown(); + return *this; } @@ -844,6 +880,7 @@ Field2D &Field2D::operator*=(const Field2D &rhs) { } else { (*this) = (*this) * rhs; } + return *this; } @@ -903,6 +940,7 @@ Field2D &Field2D::operator/=(const Field2D &rhs) { } else { (*this) = (*this) / rhs; } + return *this; } @@ -962,6 +1000,7 @@ Field2D &Field2D::operator+=(const Field2D &rhs) { } else { (*this) = (*this) + rhs; } + return *this; } @@ -1021,6 +1060,7 @@ Field2D &Field2D::operator-=(const Field2D &rhs) { } else { (*this) = (*this) - rhs; } + return *this; } @@ -1058,6 +1098,7 @@ Field2D &Field2D::operator*=(const BoutReal rhs) { } else { (*this) = (*this) * rhs; } + return *this; } @@ -1095,6 +1136,7 @@ Field2D &Field2D::operator/=(const BoutReal rhs) { } else { (*this) = (*this) / rhs; } + return *this; } @@ -1132,6 +1174,7 @@ Field2D &Field2D::operator+=(const BoutReal rhs) { } else { (*this) = (*this) + rhs; } + return *this; } @@ -1169,6 +1212,7 @@ Field2D &Field2D::operator-=(const BoutReal rhs) { } else { (*this) = (*this) - rhs; } + return *this; } From 79b515735023eba7e33dcac6d76f4bfae8260c43 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Wed, 18 Jul 2018 11:10:28 +0100 Subject: [PATCH 3/8] Add region arguments for toFieldAligned/fromFieldAligned Add region arguments (where it is valid to give RGN_NOX or RGN_NOBNDRY) so functions like toFieldAligned/fromFieldAligned can be used both when y-guard cells have been set and when they have not. e.g. when using fromFieldAligned on the results of interpolation or derivatives, y-guard cells cannot be included, but when using toFieldAligned on the inputs to interpolation or derivatives, y-guard cells must be included. --- include/bout/mesh.hxx | 8 +++---- include/bout/paralleltransform.hxx | 18 +++++++-------- src/mesh/index_derivs.cxx | 2 +- src/mesh/interpolation.cxx | 2 +- src/mesh/parallel/fci.hxx | 4 ++-- src/mesh/parallel/shiftedmetric.cxx | 35 ++++++++++++++++------------- 6 files changed, 37 insertions(+), 32 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index 056294bbe0..1524923515 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -610,12 +610,12 @@ class Mesh { typedef BoutReal (*flux_func)(stencil&, stencil &); /// Transform a field into field-aligned coordinates - const Field3D toFieldAligned(const Field3D &f) { - return getParallelTransform().toFieldAligned(f); + const Field3D toFieldAligned(const Field3D &f, const REGION region = RGN_NOX) { + return getParallelTransform().toFieldAligned(f, region); } /// Convert back into standard form - const Field3D fromFieldAligned(const Field3D &f) { - return getParallelTransform().fromFieldAligned(f); + const Field3D fromFieldAligned(const Field3D &f, const REGION region = RGN_NOX) { + return getParallelTransform().fromFieldAligned(f, region); } bool canToFromFieldAligned() { diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index a25540354a..bab43dd61e 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -38,11 +38,11 @@ public: /// Convert a 3D field into field-aligned coordinates /// so that the y index is along the magnetic field - virtual const Field3D toFieldAligned(const Field3D &f) = 0; + virtual const Field3D toFieldAligned(const Field3D &f, const REGION region = RGN_NOX) = 0; /// Convert back from field-aligned coordinates /// into standard form - virtual const Field3D fromFieldAligned(const Field3D &f) = 0; + virtual const Field3D fromFieldAligned(const Field3D &f, const REGION region = RGN_NOX) = 0; virtual bool canToFromFieldAligned() = 0; }; @@ -65,7 +65,7 @@ public: * The field is already aligned in Y, so this * does nothing */ - const Field3D toFieldAligned(const Field3D &f) override { + const Field3D toFieldAligned(const Field3D &f, const REGION UNUSED(region)) override { return f; } @@ -73,7 +73,7 @@ public: * The field is already aligned in Y, so this * does nothing */ - const Field3D fromFieldAligned(const Field3D &f) override { + const Field3D fromFieldAligned(const Field3D &f, const REGION UNUSED(region)) override { return f; } @@ -109,13 +109,13 @@ public: * in X-Z, and the metric tensor will need to be changed * if X derivatives are used. */ - const Field3D toFieldAligned(const Field3D &f) override; + const Field3D toFieldAligned(const Field3D &f, const REGION region=RGN_NOX) override; /*! * Converts a field back to X-Z orthogonal coordinates * from field aligned coordinates. */ - const Field3D fromFieldAligned(const Field3D &f) override; + const Field3D fromFieldAligned(const Field3D &f, const REGION region=RGN_NOX) override; bool canToFromFieldAligned() override{ return true; @@ -142,7 +142,7 @@ private: * Shift a 2D field in Z. * Since 2D fields are constant in Z, this has no effect */ - const Field2D shiftZ(const Field2D &f, const Field2D &UNUSED(zangle)){return f;}; + const Field2D shiftZ(const Field2D &f, const Field2D &UNUSED(zangle), const REGION UNUSED(region)=RGN_NOX){return f;}; /*! * Shift a 3D field \p f in Z by the given \p zangle @@ -151,7 +151,7 @@ private: * @param[in] zangle Toroidal angle (z) * */ - const Field3D shiftZ(const Field3D &f, const Field2D &zangle); + const Field3D shiftZ(const Field3D &f, const Field2D &zangle, const REGION region=RGN_NOX); /*! * Shift a 3D field \p f by the given phase \p phs in Z @@ -162,7 +162,7 @@ private: * @param[in] f The field to shift * @param[in] phs The phase to shift by */ - const Field3D shiftZ(const Field3D &f, const arr3Dvec &phs); + const Field3D shiftZ(const Field3D &f, const arr3Dvec &phs, const REGION region=RGN_NOX); /*! * Shift a given 1D array, assumed to be in Z, by the given \p zangle diff --git a/src/mesh/index_derivs.cxx b/src/mesh/index_derivs.cxx index f684cce292..1b6ba045f9 100644 --- a/src/mesh/index_derivs.cxx +++ b/src/mesh/index_derivs.cxx @@ -2201,7 +2201,7 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo } } - result = this->fromFieldAligned(result); + result = this->fromFieldAligned(result, RGN_NOBNDRY); } } else { // Non-staggered case diff --git a/src/mesh/interpolation.cxx b/src/mesh/interpolation.cxx index fde1497f7d..91ce7dcbf9 100644 --- a/src/mesh/interpolation.cxx +++ b/src/mesh/interpolation.cxx @@ -209,7 +209,7 @@ const Field3D interp_to(const Field3D &var, CELL_LOC loc, REGION region) { } } - result = fieldmesh->fromFieldAligned(result); + result = fieldmesh->fromFieldAligned(result, RGN_NOBNDRY); } break; } diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index 293113b91d..747f311c03 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -73,11 +73,11 @@ public: void integrateYUpDown(Field3D &f) override; - const Field3D toFieldAligned(const Field3D &UNUSED(f)) override { + const Field3D toFieldAligned(const Field3D &UNUSED(f), const REGION UNUSED(region)) override { throw BoutException("FCI method cannot transform into field aligned grid"); } - const Field3D fromFieldAligned(const Field3D &UNUSED(f)) override { + const Field3D fromFieldAligned(const Field3D &UNUSED(f), const REGION UNUSED(region)) override { throw BoutException("FCI method cannot transform into field aligned grid"); } diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index 80fdc37274..53a5fdea96 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -129,30 +129,29 @@ void ShiftedMetric::calcYUpDown(Field3D &f) { * Shift the field so that X-Z is not orthogonal, * and Y is then field aligned. */ -const Field3D ShiftedMetric::toFieldAligned(const Field3D &f) { - return shiftZ(f, toAlignedPhs); +const Field3D ShiftedMetric::toFieldAligned(const Field3D &f, const REGION region) { + return shiftZ(f, toAlignedPhs, region); } /*! * Shift back, so that X-Z is orthogonal, * but Y is not field aligned. */ -const Field3D ShiftedMetric::fromFieldAligned(const Field3D &f) { - return shiftZ(f, fromAlignedPhs); +const Field3D ShiftedMetric::fromFieldAligned(const Field3D &f, const REGION region) { + return shiftZ(f, fromAlignedPhs, region); } -const Field3D ShiftedMetric::shiftZ(const Field3D &f, const arr3Dvec &phs) { +const Field3D ShiftedMetric::shiftZ(const Field3D &f, const arr3Dvec &phs, const REGION region) { ASSERT1(&mesh == f.getMesh()); + ASSERT1(region == RGN_NOX || region == RGN_NOBNDRY); // Never calculate x-guard cells here if(mesh.LocalNz == 1) return f; // Shifting makes no difference Field3D result(&mesh); result.allocate(); - - for(int jx=0;jx &phs, } //Old approach retained so we can still specify a general zShift -const Field3D ShiftedMetric::shiftZ(const Field3D &f, const Field2D &zangle) { +const Field3D ShiftedMetric::shiftZ(const Field3D &f, const Field2D &zangle, const REGION region) { ASSERT1(&mesh == f.getMesh()); + ASSERT1(region == RGN_NOX || region == RGN_NOBNDRY); // Never calculate x-guard cells here + ASSERT1(f.getLocation() == zangle.getLocation()); if(mesh.LocalNz == 1) return f; // Shifting makes no difference Field3D result(&mesh); result.allocate(); - for(int jx=0;jx Date: Fri, 26 Oct 2018 15:45:42 +0100 Subject: [PATCH 4/8] Reset yup/ydown of fields in Solver before running rhs Ensure that no fields in the rhs function/method are using yup/ydown before calling communicate. --- src/solver/solver.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index 2267c2f06f..912b61e1b3 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -982,6 +982,7 @@ void Solver::load_vars(BoutReal *udata) { for(const auto& f : f3d) { f.var->allocate(); f.var->setLocation(f.location); + f.var->deleteYupYdown(); // reset yup/ydown fields since f.var is updated } loop_vars(udata, LOAD_VARS); From fb29665a1ef57a508ec00a8803c7968237e5fc05 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 22 May 2018 22:46:04 +0100 Subject: [PATCH 5/8] Allow calcYUpDown to be called through Mesh --- include/bout/mesh.hxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index 1524923515..6c9dea8b11 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -609,6 +609,12 @@ class Mesh { /// Derivative functions of a velocity field, and field stencil v, f typedef BoutReal (*flux_func)(stencil&, stencil &); + /// Calculate yup/ydown fields in case they can be computed for an + /// intermediate variable without communicating + void calcYUpDown(Field3D &f) { + getParallelTransform().calcYUpDown(f); + } + /// Transform a field into field-aligned coordinates const Field3D toFieldAligned(const Field3D &f, const REGION region = RGN_NOX) { return getParallelTransform().toFieldAligned(f, region); From 4a7cbcfc9b80db86b6454552cb003569d7ffa0d4 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 29 Oct 2018 17:58:50 +0000 Subject: [PATCH 6/8] Add hasValidYUpDown and set to false instead of calling deleteYupYdown Avoids cost of new/delete. --- include/bout/paralleltransform.hxx | 5 ++++- include/field3d.hxx | 13 ++++++++++++- src/field/field3d.cxx | 8 +++++--- src/field/gen_fieldops.jinja | 2 +- src/field/generated_fieldops.cxx | 24 ++++++++++++------------ src/mesh/parallel/fci.cxx | 4 ++++ src/mesh/parallel/shiftedmetric.cxx | 2 ++ src/solver/solver.cxx | 2 +- 8 files changed, 41 insertions(+), 19 deletions(-) diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index bab43dd61e..1546bf57ab 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -59,7 +59,10 @@ public: * Merges the yup and ydown() fields of f, so that * f.yup() = f.ydown() = f */ - void calcYUpDown(Field3D &f) override {f.mergeYupYdown();} + void calcYUpDown(Field3D &f) override { + f.mergeYupYdown(); + f.setHasValidYUpDown(true); + } /*! * The field is already aligned in Y, so this diff --git a/include/field3d.hxx b/include/field3d.hxx index 8d4ad7f9ec..a8a2e8ee74 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -231,7 +231,15 @@ class Field3D : public Field, public FieldData { /// Check if this field has yup and ydown fields bool hasYupYdown() const { - return (yup_field != nullptr) && (ydown_field != nullptr); + return hasValidYUpDown && (yup_field != nullptr) && (ydown_field != nullptr); + } + + /// Set validity state of yup/ydown fields + void setHasValidYUpDown(bool set) { + if (set) { + ASSERT1(yup_field != nullptr && ydown_field != nullptr); + } + hasValidYUpDown = set; } /// Return reference to yup field @@ -462,6 +470,9 @@ private: Field3D *deriv; ///< Time derivative (may be NULL) + /// flag to record whether yup_field and ydown_field have been set correctly + bool hasValidYUpDown; + /// Pointers to fields containing values along Y Field3D *yup_field, *ydown_field; }; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index eb117cf734..624878ba46 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -310,7 +310,7 @@ Field3D & Field3D::operator=(const Field3D &rhs) { setLocation(rhs.location); - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -333,7 +333,7 @@ Field3D & Field3D::operator=(const Field2D &rhs) { /// Only 3D fields have locations for now //location = CELL_CENTRE; - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -353,6 +353,8 @@ void Field3D::operator=(const FieldPerp &rhs) { BOUT_FOR(i, region_all) { (*this)(i, rhs.getIndex()) = rhs[i]; } + + setHasValidYUpDown(false); } Field3D & Field3D::operator=(const BoutReal val) { @@ -372,7 +374,7 @@ Field3D & Field3D::operator=(const BoutReal val) { //location = CELL_CENTRE; // DON'T RE-SET LOCATION - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index d33def747e..adf9544cb1 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -97,7 +97,7 @@ } {% if (out == "Field3D") %} - deleteYupYdown(); + setHasValidYUpDown(false); {% endif %} return *this; diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 02c9151322..e030cb70b8 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -63,7 +63,7 @@ Field3D &Field3D::operator*=(const Field3D &rhs) { (*this) = (*this) * rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -125,7 +125,7 @@ Field3D &Field3D::operator/=(const Field3D &rhs) { (*this) = (*this) / rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -187,7 +187,7 @@ Field3D &Field3D::operator+=(const Field3D &rhs) { (*this) = (*this) + rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -249,7 +249,7 @@ Field3D &Field3D::operator-=(const Field3D &rhs) { (*this) = (*this) - rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -319,7 +319,7 @@ Field3D &Field3D::operator*=(const Field2D &rhs) { (*this) = (*this) * rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -391,7 +391,7 @@ Field3D &Field3D::operator/=(const Field2D &rhs) { (*this) = (*this) / rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -461,7 +461,7 @@ Field3D &Field3D::operator+=(const Field2D &rhs) { (*this) = (*this) + rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -531,7 +531,7 @@ Field3D &Field3D::operator-=(const Field2D &rhs) { (*this) = (*this) - rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -571,7 +571,7 @@ Field3D &Field3D::operator*=(const BoutReal rhs) { (*this) = (*this) * rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -611,7 +611,7 @@ Field3D &Field3D::operator/=(const BoutReal rhs) { (*this) = (*this) / rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -651,7 +651,7 @@ Field3D &Field3D::operator+=(const BoutReal rhs) { (*this) = (*this) + rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } @@ -691,7 +691,7 @@ Field3D &Field3D::operator-=(const BoutReal rhs) { (*this) = (*this) - rhs; } - deleteYupYdown(); + setHasValidYUpDown(false); return *this; } diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 25002ffed3..018b5cdb26 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -302,6 +302,8 @@ void FCITransform::calcYUpDown(Field3D &f) { // Interpolate f onto yup and ydown fields f.ynext(forward_map.dir) = forward_map.interpolate(f); f.ynext(backward_map.dir) = backward_map.interpolate(f); + + f.setHasValidYUpDown(true); } void FCITransform::integrateYUpDown(Field3D &f) { @@ -313,4 +315,6 @@ void FCITransform::integrateYUpDown(Field3D &f) { // Integrate f onto yup and ydown fields f.ynext(forward_map.dir) = forward_map.integrate(f); f.ynext(backward_map.dir) = backward_map.integrate(f); + + f.setHasValidYUpDown(true); } diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index 53a5fdea96..e6d77b2f8b 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -123,6 +123,8 @@ void ShiftedMetric::calcYUpDown(Field3D &f) { shiftZ(&(f(jx,jy-1,0)), ydownPhs[jx][jy], &(ydown(jx,jy-1,0))); } } + + f.setHasValidYUpDown(true); } /*! diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index 912b61e1b3..c51c7ca52c 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -982,7 +982,7 @@ void Solver::load_vars(BoutReal *udata) { for(const auto& f : f3d) { f.var->allocate(); f.var->setLocation(f.location); - f.var->deleteYupYdown(); // reset yup/ydown fields since f.var is updated + f.var->setHasValidYUpDown(false); // flag yup/ydown fields as invalid f.var is updated } loop_vars(udata, LOAD_VARS); From 2d49b15a03652c471e7518dfbb8a6f3fdb3e3de3 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 29 Oct 2018 18:06:05 +0000 Subject: [PATCH 7/8] Update unit tests with setHasValidYUpDown Tests of splitYupYdown() and mergeYupYdown() need to call field.setHasValidYUpDown(true); --- tests/unit/field/test_field3d.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/field/test_field3d.cxx b/tests/unit/field/test_field3d.cxx index 649a3abb1b..b6f5e6cd35 100644 --- a/tests/unit/field/test_field3d.cxx +++ b/tests/unit/field/test_field3d.cxx @@ -215,6 +215,7 @@ TEST_F(Field3DTest, SplitYupYDown) { EXPECT_FALSE(field.hasYupYdown()); field.splitYupYdown(); + field.setHasValidYUpDown(true); EXPECT_TRUE(field.hasYupYdown()); @@ -242,6 +243,7 @@ TEST_F(Field3DTest, MergeYupYDown) { EXPECT_FALSE(field.hasYupYdown()); field.mergeYupYdown(); + field.setHasValidYUpDown(true); EXPECT_TRUE(field.hasYupYdown()); From d8de292d57c4d18e8c2656fc6eadf2326368b417 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Fri, 2 Nov 2018 14:13:41 +0000 Subject: [PATCH 8/8] Fix location checking in ShiftedMetric::shiftZ() Fixing the low-level shiftZ method means that toFieldAligned/fromFieldAligned also do the right thing. Check that input to shiftZ is at same location as the shift angle zShift (i.e. CELL_CENTRE). Set location of result returned from zShift to be the same as the location of the input. --- src/mesh/parallel/shiftedmetric.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index e6d77b2f8b..7dbf6382ff 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -146,11 +146,13 @@ const Field3D ShiftedMetric::fromFieldAligned(const Field3D &f, const REGION reg const Field3D ShiftedMetric::shiftZ(const Field3D &f, const arr3Dvec &phs, const REGION region) { ASSERT1(&mesh == f.getMesh()); ASSERT1(region == RGN_NOX || region == RGN_NOBNDRY); // Never calculate x-guard cells here + ASSERT1(f.getLocation() == CELL_CENTRE); // only have zShift for CELL_CENTRE, so can only deal with CELL_CENTRE inputs if(mesh.LocalNz == 1) return f; // Shifting makes no difference Field3D result(&mesh); result.allocate(); + result.setLocation(f.getLocation()); for (const auto &i : mesh.getRegion2D(REGION_STRING(region))) { shiftZ(f(i.x(),i.y()), phs[i.x()][i.y()], result(i.x(),i.y())); @@ -187,6 +189,7 @@ const Field3D ShiftedMetric::shiftZ(const Field3D &f, const Field2D &zangle, con Field3D result(&mesh); result.allocate(); + result.setLocation(f.getLocation()); // We only use methods in ShiftedMetric to get fields for parallel operations // like interp_to or DDY.