From fee27c95cbf1ac53eb2e7612293e90716548f761 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 3 Nov 2023 11:51:03 +0100 Subject: [PATCH 01/71] Dump field before and after rhs evaluation for debugging --- src/solver/impls/pvode/pvode.cxx | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index b2cfd233a9..8a51a9cb19 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -293,6 +293,49 @@ BoutReal PvodeSolver::run(BoutReal tout) { // Check return flag if (flag != SUCCESS) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); + CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; + if (f2d.empty() and v2d.empty() and v3d.empty()) { + Options debug{}; + using namespace std::string_literals; + Mesh* mesh{}; + for (const auto& prefix : {"pre_"s, "residuum_"s}) { + std::vector ffs{}; + std::vector evolve_bndrys{}; + for (const auto& f : f3d) { + Field3D ff{0.}; + ff.allocate(); + ff.setLocation(f.location); + mesh = ff.getMesh(); + debug[fmt::format("{:s}{:s}", prefix, f.name)] = ff; + ffs.push_back(ff); + evolve_bndrys.push_back(f.evolve_bndry); + } + pvode_load_data_f3d(evolve_bndrys, ffs, + prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); + } + + for (auto& f : f3d) { + f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); + setName(f.var, f.name); + } + run_rhs(simtime); + + for (auto& f : f3d) { + debug[f.name] = *f.var; + } + + if (mesh) { + mesh->outputVars(debug); + debug["BOUT_VERSION"].force(bout::version::as_double); + } + + std::string outname = fmt::format( + "{}/BOUT.debug.{}.nc", + Options::root()["datadir"].withDefault("data"), BoutComm::rank()); + + bout::OptionsNetCDF(outname).write(debug); + MPI_Barrier(BoutComm::get()); + } return (-1.0); } From 96da2e9f88e313f4dd388b2c83d701046aedf96c Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 3 Nov 2023 11:49:32 +0100 Subject: [PATCH 02/71] Add setName function --- include/bout/field.hxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index c0693ec0fb..0867560c3b 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -683,4 +683,12 @@ inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { #undef FIELD_FUNC +template , class... Types> +inline T setName(T&& f, const std::string& name, Types... args) { +#if BOUT_USE_TRACK + f.name = fmt::format(name, args...); +#endif + return f; +} + #endif /* FIELD_H */ From e56981ceeb0409d7d48d81e1225e7332c0346519 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 19 Jun 2023 09:33:00 +0200 Subject: [PATCH 03/71] Set div_par and grad_par names --- src/mesh/coordinates.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 01f0fe46ca..3948c75b94 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1542,7 +1542,11 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, TRACE("Coordinates::Grad_par( Field3D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return ::DDY(var, outloc, method) * invSg(); + if (invSg == nullptr) { + invSg = std::make_unique(); + (*invSg) = 1.0 / sqrt(g_22); + } + return setName(::DDY(var, outloc, method) * invSg(), "Grad_par({:s})", var.name); } ///////////////////////////////////////////////////////// @@ -1601,7 +1605,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, f_B.yup(i) = f.yup(i) / Bxy_floc.yup(i); f_B.ydown(i) = f.ydown(i) / Bxy_floc.ydown(i); } - return Bxy * Grad_par(f_B, outloc, method); + return setName(Bxy * Grad_par(f_B, outloc, method), "Div_par({:s})", f.name); } ///////////////////////////////////////////////////////// From 6b2c132e3db61fa4f453e43a6988e8534f6c0a43 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 19 Jun 2023 09:32:25 +0200 Subject: [PATCH 04/71] Dump debug file if PVODE fails Use the new track feature (better name required) to dump the different components of the ddt() as well as the residuum for the evolved fields. --- src/solver/impls/pvode/pvode.cxx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 8a51a9cb19..7283b7d0eb 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -42,12 +42,39 @@ #include // contains the enum for types of preconditioning #include // band preconditioner function prototypes +#include + using namespace pvode; void solver_f(integer N, BoutReal t, N_Vector u, N_Vector udot, void* f_data); void solver_gloc(integer N, BoutReal t, BoutReal* u, BoutReal* udot, void* f_data); void solver_cfn(integer N, BoutReal t, N_Vector u, void* f_data); +namespace { +// local only +void pvode_load_data_f3d(const std::vector& evolve_bndrys, + std::vector& ffs, BoutReal* udata) { + int p = 0; + Mesh* mesh = ffs[0].getMesh(); + const int nz = mesh->LocalNz; + for (const auto& bndry : {true, false}) { + for (const auto& i2d : mesh->getRegion2D(bndry ? "RGN_BNDRY" : "RGN_NOBNDRY")) { + for (int jz = 0; jz < nz; jz++) { + // Loop over 3D variables + std::vector::const_iterator evolve_bndry = evolve_bndrys.begin(); + for (std::vector::iterator ff = ffs.begin(); ff != ffs.end(); ++ff) { + if (bndry && !*evolve_bndry) + continue; + (*ff)[mesh->ind2Dto3D(i2d, jz)] = udata[p]; + p++; + } + ++evolve_bndry; + } + } + } +} +} // namespace + const BoutReal ZERO = 0.0; long int iopt[OPT_SIZE]; From df2d66189f4d2e87cc024521ad287936b9c0ba85 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 19 Jun 2023 09:27:19 +0200 Subject: [PATCH 05/71] Add tracking to Field3D This keeps track of all the changes done to the field and stores them to a OptionsObject. --- include/bout/field3d.hxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index ba8c8e879e..8992575be6 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -514,6 +514,13 @@ private: /// RegionID over which the field is valid std::optional regionID; + + int tracking_state{0}; + Options* tracking{nullptr}; + std::string selfname{""}; + template + Options* track(const T& change, std::string op); + Options* track(const BoutReal& change, std::string op); }; // Non-member overloaded operators From 263f9fedaad854832bfdbf6a5ac9322eb492c71e Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 19 Jun 2023 09:27:19 +0200 Subject: [PATCH 06/71] Add tracking to Field3D This keeps track of all the changes done to the field and stores them to a OptionsObject. --- include/bout/field3d.hxx | 4 + src/field/field3d.cxx | 44 ++++ src/field/gen_fieldops.jinja | 14 ++ src/field/generated_fieldops.cxx | 348 +++++++++++++++++++++++++++++++ 4 files changed, 410 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 8992575be6..bf7a9cc180 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -295,6 +295,10 @@ public: /// cuts on closed field lines? bool requiresTwistShift(bool twist_shift_enabled); + /// Enable a special tracking mode for debugging + /// Save all changes that, are done to the field, to tracking + Field3D& enableTracking(const std::string& name, Options& tracking); + ///////////////////////////////////////////////////////// // Data access diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 011353f34a..f0f088b656 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -243,6 +243,7 @@ Field3D& Field3D::operator=(const Field3D& rhs) { } TRACE("Field3D: Assignment from Field3D"); + track(rhs, "operator="); // Copy base slice Field::operator=(rhs); @@ -263,6 +264,7 @@ Field3D& Field3D::operator=(const Field3D& rhs) { Field3D& Field3D::operator=(Field3D&& rhs) { TRACE("Field3D: Assignment from Field3D"); + track(rhs, "operator="); // Move parallel slices or delete existing ones. yup_fields = std::move(rhs.yup_fields); @@ -283,6 +285,7 @@ Field3D& Field3D::operator=(Field3D&& rhs) { Field3D& Field3D::operator=(const Field2D& rhs) { TRACE("Field3D = Field2D"); + track(rhs, "operator="); /// Check that the data is allocated ASSERT1(rhs.isAllocated()); @@ -327,6 +330,7 @@ void Field3D::operator=(const FieldPerp& rhs) { Field3D& Field3D::operator=(const BoutReal val) { TRACE("Field3D = BoutReal"); + track(val, "operator="); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -831,3 +835,43 @@ Field3D::getValidRegionWithDefault(const std::string& region_name) const { void Field3D::setRegion(const std::string& region_name) { regionID = fieldmesh->getRegionID(region_name); } + +Field3D& Field3D::enableTracking(const std::string& name, Options& _tracking) { + tracking = &_tracking; + tracking_state = 1; + selfname = name; + return *this; +} + +template +Options* Field3D::track(const T& change, std::string op) { + if (tracking and tracking_state) { + const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; + tracking->set(outname, change, "tracking"); + (*tracking)[outname].setAttributes({ + {"operation", op}, +#if BOUT_USE_TRACK + {"rhs.name", change.name}, +#endif + }); + return &(*tracking)[outname]; + } + return nullptr; +} + +template Options* Field3D::track(const Field3D&, std::string); +template Options* Field3D::track(const Field2D&, std::string); +template Options* Field3D::track(const FieldPerp&, std::string); + +Options* Field3D::track(const BoutReal& change, std::string op) { + if (tracking and tracking_state) { + const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; + tracking->set(outname, change, "tracking"); + (*tracking)[outname].setAttributes({ + {"operation", op}, + {"rhs.name", "BR"}, + }); + return &(*tracking)[outname]; + } + return nullptr; +} diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index ecd4e628cc..58b1ae28ba 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -61,6 +61,10 @@ } {% endif %} +#if BOUT_USE_TRACK + {{out.name}}.name = fmt::format("{:s} {{operator}} {:s}", {{'"BR"' if lhs == "BoutReal" else lhs.name + ".name"}} + , {{'"BR"' if rhs == "BoutReal" else rhs.name + ".name"}}); +#endif checkData({{out.name}}); return {{out.name}}; } @@ -129,9 +133,19 @@ } {% endif %} + {% if lhs == "Field3D" %} + track(rhs, "operator{{operator}}="); + {% endif %} +#if BOUT_USE_TRACK + name = fmt::format("{:s} {{operator}}= {:s}", this->name, {{'"BR"' if rhs == "BoutReal" else rhs.name + ".name"}}); +#endif + checkData(*this); } else { + {% if lhs == "Field3D" %} + track(rhs, "operator{{operator}}="); + {% endif %} (*this) = (*this) {{operator}} {{rhs.name}}; } return *this; diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 6b778acee3..3495d87dbc 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -20,6 +20,9 @@ Field3D operator*(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -42,9 +45,15 @@ Field3D& Field3D::operator*=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator*="); (*this) = (*this) * rhs; } return *this; @@ -64,6 +73,9 @@ Field3D operator/(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -86,9 +98,15 @@ Field3D& Field3D::operator/=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator/="); (*this) = (*this) / rhs; } return *this; @@ -108,6 +126,9 @@ Field3D operator+(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -130,9 +151,15 @@ Field3D& Field3D::operator+=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator+="); (*this) = (*this) + rhs; } return *this; @@ -152,6 +179,9 @@ Field3D operator-(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -174,9 +204,15 @@ Field3D& Field3D::operator-=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator-="); (*this) = (*this) - rhs; } return *this; @@ -201,6 +237,9 @@ Field3D operator*(const Field3D& lhs, const Field2D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -226,9 +265,15 @@ Field3D& Field3D::operator*=(const Field2D& rhs) { } } + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator*="); (*this) = (*this) * rhs; } return *this; @@ -254,6 +299,9 @@ Field3D operator/(const Field3D& lhs, const Field2D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -280,9 +328,15 @@ Field3D& Field3D::operator/=(const Field2D& rhs) { } } + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator/="); (*this) = (*this) / rhs; } return *this; @@ -307,6 +361,9 @@ Field3D operator+(const Field3D& lhs, const Field2D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -332,9 +389,15 @@ Field3D& Field3D::operator+=(const Field2D& rhs) { } } + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator+="); (*this) = (*this) + rhs; } return *this; @@ -359,6 +422,9 @@ Field3D operator-(const Field3D& lhs, const Field2D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -384,9 +450,15 @@ Field3D& Field3D::operator-=(const Field2D& rhs) { } } + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { + track(rhs, "operator-="); (*this) = (*this) - rhs; } return *this; @@ -408,6 +480,9 @@ FieldPerp operator*(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -428,6 +503,9 @@ FieldPerp operator/(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -448,6 +526,9 @@ FieldPerp operator+(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -468,6 +549,9 @@ FieldPerp operator-(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -485,6 +569,9 @@ Field3D operator*(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -504,9 +591,15 @@ Field3D& Field3D::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { + track(rhs, "operator*="); (*this) = (*this) * rhs; } return *this; @@ -526,6 +619,9 @@ Field3D operator/(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -546,9 +642,15 @@ Field3D& Field3D::operator/=(const BoutReal rhs) { const auto tmp = 1.0 / rhs; BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= tmp; } + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { + track(rhs, "operator/="); (*this) = (*this) / rhs; } return *this; @@ -567,6 +669,9 @@ Field3D operator+(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -586,9 +691,15 @@ Field3D& Field3D::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, "BR"); +#endif + checkData(*this); } else { + track(rhs, "operator+="); (*this) = (*this) + rhs; } return *this; @@ -607,6 +718,9 @@ Field3D operator-(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -626,9 +740,15 @@ Field3D& Field3D::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { + track(rhs, "operator-="); (*this) = (*this) - rhs; } return *this; @@ -653,6 +773,9 @@ Field3D operator*(const Field2D& lhs, const Field3D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -676,6 +799,9 @@ Field3D operator/(const Field2D& lhs, const Field3D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -699,6 +825,9 @@ Field3D operator+(const Field2D& lhs, const Field3D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -722,6 +851,9 @@ Field3D operator-(const Field2D& lhs, const Field3D& rhs) { } } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -738,6 +870,9 @@ Field2D operator*(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -754,6 +889,10 @@ Field2D& Field2D::operator*=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -774,6 +913,9 @@ Field2D operator/(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -790,6 +932,10 @@ Field2D& Field2D::operator/=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -810,6 +956,9 @@ Field2D operator+(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -826,6 +975,10 @@ Field2D& Field2D::operator+=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -846,6 +999,9 @@ Field2D operator-(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -862,6 +1018,10 @@ Field2D& Field2D::operator-=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -886,6 +1046,9 @@ FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -906,6 +1069,9 @@ FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -926,6 +1092,9 @@ FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -946,6 +1115,9 @@ FieldPerp operator-(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -961,6 +1133,9 @@ Field2D operator*(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -976,6 +1151,10 @@ Field2D& Field2D::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -996,6 +1175,9 @@ Field2D operator/(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1012,6 +1194,10 @@ Field2D& Field2D::operator/=(const BoutReal rhs) { const auto tmp = 1.0 / rhs; BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= tmp; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1031,6 +1217,9 @@ Field2D operator+(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1046,6 +1235,10 @@ Field2D& Field2D::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1065,6 +1258,9 @@ Field2D operator-(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1080,6 +1276,10 @@ Field2D& Field2D::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1104,6 +1304,9 @@ FieldPerp operator*(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] * rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1126,6 +1329,10 @@ FieldPerp& FieldPerp::operator*=(const Field3D& rhs) { (*this)[index] *= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1150,6 +1357,9 @@ FieldPerp operator/(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] / rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1172,6 +1382,10 @@ FieldPerp& FieldPerp::operator/=(const Field3D& rhs) { (*this)[index] /= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1196,6 +1410,9 @@ FieldPerp operator+(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] + rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1218,6 +1435,10 @@ FieldPerp& FieldPerp::operator+=(const Field3D& rhs) { (*this)[index] += rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1242,6 +1463,9 @@ FieldPerp operator-(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] - rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1264,6 +1488,10 @@ FieldPerp& FieldPerp::operator-=(const Field3D& rhs) { (*this)[index] -= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1288,6 +1516,9 @@ FieldPerp operator*(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] * rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1310,6 +1541,10 @@ FieldPerp& FieldPerp::operator*=(const Field2D& rhs) { (*this)[index] *= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1334,6 +1569,9 @@ FieldPerp operator/(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] / rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1356,6 +1594,10 @@ FieldPerp& FieldPerp::operator/=(const Field2D& rhs) { (*this)[index] /= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1380,6 +1622,9 @@ FieldPerp operator+(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] + rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1402,6 +1647,10 @@ FieldPerp& FieldPerp::operator+=(const Field2D& rhs) { (*this)[index] += rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1426,6 +1675,9 @@ FieldPerp operator-(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] - rhs[base_ind]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1448,6 +1700,10 @@ FieldPerp& FieldPerp::operator-=(const Field2D& rhs) { (*this)[index] -= rhs[base_ind]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1468,6 +1724,9 @@ FieldPerp operator*(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1484,6 +1743,10 @@ FieldPerp& FieldPerp::operator*=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1504,6 +1767,9 @@ FieldPerp operator/(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1520,6 +1786,10 @@ FieldPerp& FieldPerp::operator/=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1540,6 +1810,9 @@ FieldPerp operator+(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1556,6 +1829,10 @@ FieldPerp& FieldPerp::operator+=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1576,6 +1853,9 @@ FieldPerp operator-(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif checkData(result); return result; } @@ -1592,6 +1872,10 @@ FieldPerp& FieldPerp::operator-=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + checkData(*this); } else { @@ -1611,6 +1895,9 @@ FieldPerp operator*(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1626,6 +1913,10 @@ FieldPerp& FieldPerp::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1646,6 +1937,9 @@ FieldPerp operator/(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1661,6 +1955,10 @@ FieldPerp& FieldPerp::operator/=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1680,6 +1978,9 @@ FieldPerp operator+(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1695,6 +1996,10 @@ FieldPerp& FieldPerp::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1714,6 +2019,9 @@ FieldPerp operator-(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); +#endif checkData(result); return result; } @@ -1729,6 +2037,10 @@ FieldPerp& FieldPerp::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, "BR"); +#endif + checkData(*this); } else { @@ -1750,6 +2062,9 @@ Field3D operator*(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1767,6 +2082,9 @@ Field3D operator/(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1784,6 +2102,9 @@ Field3D operator+(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1801,6 +2122,9 @@ Field3D operator-(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1816,6 +2140,9 @@ Field2D operator*(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1831,6 +2158,9 @@ Field2D operator/(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1846,6 +2176,9 @@ Field2D operator+(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1861,6 +2194,9 @@ Field2D operator-(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1876,6 +2212,9 @@ FieldPerp operator*(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs * rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1891,6 +2230,9 @@ FieldPerp operator/(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs / rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1906,6 +2248,9 @@ FieldPerp operator+(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs + rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); +#endif checkData(result); return result; } @@ -1921,6 +2266,9 @@ FieldPerp operator-(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs - rhs[index]; } +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); +#endif checkData(result); return result; } From bac4ca92a31b60c40e87dd47b2ef764f571a58be Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 25 Apr 2023 09:16:38 +0200 Subject: [PATCH 07/71] cvode: Add option to use Adams Moulton solver instead of BDF --- src/solver/impls/pvode/pvode.cxx | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 7283b7d0eb..ae5cd783a8 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -214,7 +214,34 @@ int PvodeSolver::init() { } iopt[MXSTEP] = pvode_mxstep; - cvode_mem = CVodeMalloc(neq, solver_f, simtime, u, BDF, NEWTON, SS, &reltol, &abstol, + { + /* ropt[H0] : initial step size. Optional input. */ + + /* ropt[HMAX] : maximum absolute value of step size allowed. * + * Optional input. (Default is infinity). */ + const BoutReal hmax( + (*options)["max_timestep"].doc("Maximum internal timestep").withDefault(-1.)); + if (hmax > 0) { + ropt[HMAX] = hmax; + } + /* ropt[HMIN] : minimum absolute value of step size allowed. * + * Optional input. (Default is 0.0). */ + const BoutReal hmin( + (*options)["min_timestep"].doc("Minimum internal timestep").withDefault(-1.)); + if (hmin > 0) { + ropt[HMIN] = hmin; + } + /* iopt[MAXORD] : maximum lmm order to be used by the solver. * + * Optional input. (Default = 12 for ADAMS, 5 for * + * BDF). */ + const int maxOrder((*options)["max_order"].doc("Maximum order").withDefault(-1)); + if (maxOrder > 0) { + iopt[MAXORD] = maxOrder; + } + } + const bool use_adam((*options)["adams_moulton"].doc("Use Adams Moulton solver instead of BDF").withDefault(false)); + + cvode_mem = CVodeMalloc(neq, solver_f, simtime, u, use_adam ? ADAMS : BDF, NEWTON, SS, &reltol, &abstol, this, nullptr, optIn, iopt, ropt, machEnv); if (cvode_mem == nullptr) { From 708bdcb2ff0a5c346edb43f7e609949b7c7afbd9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 29 Mar 2023 12:59:22 +0200 Subject: [PATCH 08/71] Expose more pvode option to user --- src/solver/impls/pvode/pvode.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index ae5cd783a8..ac6e981b50 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -212,6 +212,9 @@ int PvodeSolver::init() { for (i = 0; i < OPT_SIZE; i++) { ropt[i] = ZERO; } + /* iopt[MXSTEP] : maximum number of internal steps to be taken by * + * the solver in its attempt to reach tout. * + * Optional input. (Default = 500). */ iopt[MXSTEP] = pvode_mxstep; { From d88b454aa2b2924a26a180440f956911c05a0abc Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 19 Mar 2024 16:04:48 +0100 Subject: [PATCH 09/71] Fix bad cherry-pick --- src/mesh/coordinates.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3948c75b94..32774d6229 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1542,10 +1542,6 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, TRACE("Coordinates::Grad_par( Field3D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - if (invSg == nullptr) { - invSg = std::make_unique(); - (*invSg) = 1.0 / sqrt(g_22); - } return setName(::DDY(var, outloc, method) * invSg(), "Grad_par({:s})", var.name); } From 023bc41730de39040a50ae245363945d2447d63b Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 19 Mar 2024 16:35:43 +0100 Subject: [PATCH 10/71] Update to new API --- include/bout/field.hxx | 7 +++++++ src/solver/impls/pvode/pvode.cxx | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 0867560c3b..04035f5b76 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -683,6 +683,13 @@ inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { #undef FIELD_FUNC +template , class... Types> +inline void setName(T& f, const std::string& name, Types... args) { +#if BOUT_USE_TRACK + f.name = fmt::format(name, args...); +#endif +} + template , class... Types> inline T setName(T&& f, const std::string& name, Types... args) { #if BOUT_USE_TRACK diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index ac6e981b50..762fba32d1 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -373,7 +373,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); - setName(f.var, f.name); + setName(*f.var, f.name); } run_rhs(simtime); @@ -390,7 +390,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { "{}/BOUT.debug.{}.nc", Options::root()["datadir"].withDefault("data"), BoutComm::rank()); - bout::OptionsNetCDF(outname).write(debug); + bout::OptionsIO::create(outname)->write(debug); MPI_Barrier(BoutComm::get()); } return (-1.0); From affc995c4ba482c79677c890cc44ccb47d45b648 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 19 Mar 2024 16:35:53 +0100 Subject: [PATCH 11/71] Fix documentation --- manual/sphinx/user_docs/bout_options.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/sphinx/user_docs/bout_options.rst b/manual/sphinx/user_docs/bout_options.rst index 85a8a17d59..330a0dad7e 100644 --- a/manual/sphinx/user_docs/bout_options.rst +++ b/manual/sphinx/user_docs/bout_options.rst @@ -889,7 +889,7 @@ Fields can also be stored and written:: Options fields; fields["f2d"] = Field2D(1.0); fields["f3d"] = Field3D(2.0); - bout::OptionsIO::create("fields.nc").write(fields); + bout::OptionsIO::create("fields.nc")->write(fields); This allows the input settings and evolving variables to be combined into a single tree (see above on joining trees) and written From 71f5b6adb6a8ad7b8941ba783773897906d870d2 Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Tue, 19 Mar 2024 15:50:33 +0000 Subject: [PATCH 12/71] Apply clang-format changes --- src/solver/impls/pvode/pvode.cxx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 762fba32d1..a12f330964 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -242,10 +242,12 @@ int PvodeSolver::init() { iopt[MAXORD] = maxOrder; } } - const bool use_adam((*options)["adams_moulton"].doc("Use Adams Moulton solver instead of BDF").withDefault(false)); + const bool use_adam((*options)["adams_moulton"] + .doc("Use Adams Moulton solver instead of BDF") + .withDefault(false)); - cvode_mem = CVodeMalloc(neq, solver_f, simtime, u, use_adam ? ADAMS : BDF, NEWTON, SS, &reltol, &abstol, - this, nullptr, optIn, iopt, ropt, machEnv); + cvode_mem = CVodeMalloc(neq, solver_f, simtime, u, use_adam ? ADAMS : BDF, NEWTON, SS, + &reltol, &abstol, this, nullptr, optIn, iopt, ropt, machEnv); if (cvode_mem == nullptr) { throw BoutException("\tError: CVodeMalloc failed.\n"); @@ -373,12 +375,12 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); - setName(*f.var, f.name); + setName(*f.var, f.name); } run_rhs(simtime); for (auto& f : f3d) { - debug[f.name] = *f.var; + debug[f.name] = *f.var; } if (mesh) { From 31fd46153fad6977524394179d0b83ac51f26b9e Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 20 Mar 2024 09:59:13 +0100 Subject: [PATCH 13/71] Apply recomendations from code-review --- include/bout/field3d.hxx | 6 +++--- src/field/field3d.cxx | 10 +++++----- src/solver/impls/pvode/pvode.cxx | 5 +++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index bf7a9cc180..cfde9e5328 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -521,10 +521,10 @@ private: int tracking_state{0}; Options* tracking{nullptr}; - std::string selfname{""}; + std::string selfname; template - Options* track(const T& change, std::string op); - Options* track(const BoutReal& change, std::string op); + Options* track(const T& change, std::string operation); + Options* track(const BoutReal& change, std::string operation); }; // Non-member overloaded operators diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index f0f088b656..2196d6eea4 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -844,12 +844,12 @@ Field3D& Field3D::enableTracking(const std::string& name, Options& _tracking) { } template -Options* Field3D::track(const T& change, std::string op) { - if (tracking and tracking_state) { +Options* Field3D::track(const T& change, std::string operation) { + if (tracking != nullptr and tracking_state != 0) { const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; tracking->set(outname, change, "tracking"); (*tracking)[outname].setAttributes({ - {"operation", op}, + {"operation", operation}, #if BOUT_USE_TRACK {"rhs.name", change.name}, #endif @@ -863,12 +863,12 @@ template Options* Field3D::track(const Field3D&, std::string); template Options* Field3D::track(const Field2D&, std::string); template Options* Field3D::track(const FieldPerp&, std::string); -Options* Field3D::track(const BoutReal& change, std::string op) { +Options* Field3D::track(const BoutReal& change, std::string operation) { if (tracking and tracking_state) { const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; tracking->set(outname, change, "tracking"); (*tracking)[outname].setAttributes({ - {"operation", op}, + {"operation", operation}, {"rhs.name", "BR"}, }); return &(*tracking)[outname]; diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index a12f330964..f3a96b03af 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -53,7 +53,7 @@ void solver_cfn(integer N, BoutReal t, N_Vector u, void* f_data); namespace { // local only void pvode_load_data_f3d(const std::vector& evolve_bndrys, - std::vector& ffs, BoutReal* udata) { + std::vector& ffs, const BoutReal* udata) { int p = 0; Mesh* mesh = ffs[0].getMesh(); const int nz = mesh->LocalNz; @@ -63,8 +63,9 @@ void pvode_load_data_f3d(const std::vector& evolve_bndrys, // Loop over 3D variables std::vector::const_iterator evolve_bndry = evolve_bndrys.begin(); for (std::vector::iterator ff = ffs.begin(); ff != ffs.end(); ++ff) { - if (bndry && !*evolve_bndry) + if (bndry && !*evolve_bndry) { continue; + } (*ff)[mesh->ind2Dto3D(i2d, jz)] = udata[p]; p++; } From 17e46cfc1c0a835fea474ac68f64a9addbf4379f Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 20 Mar 2024 10:02:28 +0100 Subject: [PATCH 14/71] Use more meaningful names --- src/solver/impls/pvode/pvode.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index f3a96b03af..c389a3c0d1 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -359,18 +359,18 @@ BoutReal PvodeSolver::run(BoutReal tout) { using namespace std::string_literals; Mesh* mesh{}; for (const auto& prefix : {"pre_"s, "residuum_"s}) { - std::vector ffs{}; + std::vector list_of_fields{}; std::vector evolve_bndrys{}; for (const auto& f : f3d) { - Field3D ff{0.}; - ff.allocate(); - ff.setLocation(f.location); - mesh = ff.getMesh(); - debug[fmt::format("{:s}{:s}", prefix, f.name)] = ff; - ffs.push_back(ff); + mesh = f.var->getMesh(); + Field3D to_load{0., mesh}; + to_load.allocate(); + to_load.setLocation(f.location); + debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; + list_of_fields.push_back(to_load); evolve_bndrys.push_back(f.evolve_bndry); } - pvode_load_data_f3d(evolve_bndrys, ffs, + pvode_load_data_f3d(evolve_bndrys, list_of_fields, prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); } From 9c0ae16ed905588b50f3e4fe634dcedf47de22b5 Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Wed, 20 Mar 2024 09:03:10 +0000 Subject: [PATCH 15/71] Apply clang-format changes --- src/solver/impls/pvode/pvode.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index c389a3c0d1..fe231e1086 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -65,7 +65,7 @@ void pvode_load_data_f3d(const std::vector& evolve_bndrys, for (std::vector::iterator ff = ffs.begin(); ff != ffs.end(); ++ff) { if (bndry && !*evolve_bndry) { continue; - } + } (*ff)[mesh->ind2Dto3D(i2d, jz)] = udata[p]; p++; } From 4a17b4982df9788fc26407db70f14d0ce16098e3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 20 Mar 2024 10:04:52 +0100 Subject: [PATCH 16/71] Apply suggestions from code review --- src/solver/impls/pvode/pvode.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index fe231e1086..db28f64d86 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -384,12 +384,12 @@ BoutReal PvodeSolver::run(BoutReal tout) { debug[f.name] = *f.var; } - if (mesh) { + if (mesh != nullptr) { mesh->outputVars(debug); debug["BOUT_VERSION"].force(bout::version::as_double); } - std::string outname = fmt::format( + const std::string outname = fmt::format( "{}/BOUT.debug.{}.nc", Options::root()["datadir"].withDefault("data"), BoutComm::rank()); From 2f7c3c0664c954c016b949ea8c199f6f35ac289f Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 20 Mar 2024 16:02:22 +0100 Subject: [PATCH 17/71] Workaround for gcc 9.4 gcc 9.4 is unable to correctly parse the construction for the function argument, if name.change is used directly. First making a copy seems to work around that issue. --- src/field/field3d.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 2196d6eea4..e0d4dda01d 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -848,10 +848,14 @@ Options* Field3D::track(const T& change, std::string operation) { if (tracking != nullptr and tracking_state != 0) { const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; tracking->set(outname, change, "tracking"); + // Workaround for bug in gcc9.4 +#if BOUT_USE_TRACK + const std::string changename = change.name; +#endif (*tracking)[outname].setAttributes({ {"operation", operation}, #if BOUT_USE_TRACK - {"rhs.name", change.name}, + {"rhs.name", changename}, #endif }); return &(*tracking)[outname]; From d611758ae6b02a93e51eeeaebe025b628a23c9b3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 9 Apr 2024 15:15:30 +0200 Subject: [PATCH 18/71] Add option to debug on failure --- src/solver/impls/pvode/pvode.cxx | 80 ++++++++++++++++++-------------- src/solver/impls/pvode/pvode.hxx | 9 +++- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index db28f64d86..9dce5d357f 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -247,6 +247,11 @@ int PvodeSolver::init() { .doc("Use Adams Moulton solver instead of BDF") .withDefault(false)); + debug_on_failure = + (*options)["debug_on_failure"] + .doc("Run an aditional rhs if the solver fails with extra tracking") + .withDefault(false); + cvode_mem = CVodeMalloc(neq, solver_f, simtime, u, use_adam ? ADAMS : BDF, NEWTON, SS, &reltol, &abstol, this, nullptr, optIn, iopt, ropt, machEnv); @@ -354,47 +359,52 @@ BoutReal PvodeSolver::run(BoutReal tout) { if (flag != SUCCESS) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; - if (f2d.empty() and v2d.empty() and v3d.empty()) { - Options debug{}; - using namespace std::string_literals; - Mesh* mesh{}; - for (const auto& prefix : {"pre_"s, "residuum_"s}) { - std::vector list_of_fields{}; - std::vector evolve_bndrys{}; - for (const auto& f : f3d) { - mesh = f.var->getMesh(); - Field3D to_load{0., mesh}; - to_load.allocate(); - to_load.setLocation(f.location); - debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; - list_of_fields.push_back(to_load); - evolve_bndrys.push_back(f.evolve_bndry); + if (debug_on_failure) { + if (f2d.empty() and v2d.empty() and v3d.empty()) { + Options debug{}; + using namespace std::string_literals; + Mesh* mesh{}; + for (const auto& prefix : {"pre_"s, "residuum_"s}) { + std::vector list_of_fields{}; + std::vector evolve_bndrys{}; + for (const auto& f : f3d) { + mesh = f.var->getMesh(); + Field3D to_load{0., mesh}; + to_load.allocate(); + to_load.setLocation(f.location); + debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; + list_of_fields.push_back(to_load); + evolve_bndrys.push_back(f.evolve_bndry); + } + pvode_load_data_f3d(evolve_bndrys, list_of_fields, + prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); } - pvode_load_data_f3d(evolve_bndrys, list_of_fields, - prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); - } - for (auto& f : f3d) { - f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); - setName(*f.var, f.name); - } - run_rhs(simtime); + for (auto& f : f3d) { + f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); + setName(*f.var, f.name); + } + run_rhs(simtime); - for (auto& f : f3d) { - debug[f.name] = *f.var; - } + for (auto& f : f3d) { + debug[f.name] = *f.var; + } - if (mesh != nullptr) { - mesh->outputVars(debug); - debug["BOUT_VERSION"].force(bout::version::as_double); - } + if (mesh != nullptr) { + mesh->outputVars(debug); + debug["BOUT_VERSION"].force(bout::version::as_double); + } - const std::string outname = fmt::format( - "{}/BOUT.debug.{}.nc", - Options::root()["datadir"].withDefault("data"), BoutComm::rank()); + const std::string outname = + fmt::format("{}/BOUT.debug.{}.nc", + Options::root()["datadir"].withDefault("data"), + BoutComm::rank()); - bout::OptionsIO::create(outname)->write(debug); - MPI_Barrier(BoutComm::get()); + bout::OptionsIO::create(outname)->write(debug); + MPI_Barrier(BoutComm::get()); + } else { + output_warn.write("debug_on_failure is currently only supported for Field3Ds"); + } } return (-1.0); } diff --git a/src/solver/impls/pvode/pvode.hxx b/src/solver/impls/pvode/pvode.hxx index d29135d02e..3b385af99d 100644 --- a/src/solver/impls/pvode/pvode.hxx +++ b/src/solver/impls/pvode/pvode.hxx @@ -75,10 +75,15 @@ private: pvode::machEnvType machEnv{nullptr}; void* cvode_mem{nullptr}; - BoutReal abstol, reltol; // addresses passed in init must be preserved + BoutReal abstol, reltol; + // addresses passed in init must be preserved pvode::PVBBDData pdata{nullptr}; - bool pvode_initialised = false; + /// is pvode already initialised? + bool pvode_initialised{false}; + + /// Add debugging data if solver fails + bool debug_on_failure{false}; }; #endif // BOUT_PVODE_SOLVER_H From db96b7ecc3df8613a80203d59a421bf4186f25d1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 9 Apr 2024 15:56:25 +0200 Subject: [PATCH 19/71] Add option to euler solver to dump debug info --- src/solver/impls/euler/euler.cxx | 36 +++++++++++++++++++++++++++++++- src/solver/impls/euler/euler.hxx | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 3976f4402c..45ba5ccdbf 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -20,7 +20,10 @@ EulerSolver::EulerSolver(Options* options) .withDefault(2.)), timestep((*options)["timestep"] .doc("Internal timestep (defaults to output timestep)") - .withDefault(getOutputTimestep())) {} + .withDefault(getOutputTimestep())), + dump_at_time((*options)["dump_at_time"] + .doc("Dump debug info about the simulation") + .withDefault(-1)) {} void EulerSolver::setMaxTimestep(BoutReal dt) { if (dt >= cfl_factor * timestep) { @@ -141,7 +144,38 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star Array& result) { load_vars(std::begin(start)); + const bool dump_now = dump_at_time > 0 && std::abs(dump_at_time - curtime) < dt; + std::unique_ptr debug_ptr; + if (dump_now) { + debug_ptr = std::make_unique(); + Options& debug = *debug_ptr; + for (auto& f : f3d) { + f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); + setName(*f.var, f.name); + } + } + run_rhs(curtime); + if (dump_now) { + Options& debug = *debug_ptr; + Mesh* mesh; + for (auto& f : f3d) { + debug[f.name] = *f.var; + mesh = f.var->getMesh(); + } + + if (mesh != nullptr) { + mesh->outputVars(debug); + debug["BOUT_VERSION"].force(bout::version::as_double); + } + + const std::string outname = fmt::format( + "{}/BOUT.debug.{}.nc", + Options::root()["datadir"].withDefault("data"), BoutComm::rank()); + + bout::OptionsIO::create(outname)->write(debug); + MPI_Barrier(BoutComm::get()); + } save_derivs(std::begin(result)); BOUT_OMP_PERF(parallel for) diff --git a/src/solver/impls/euler/euler.hxx b/src/solver/impls/euler/euler.hxx index 0ee81a3d33..4b6dc60a62 100644 --- a/src/solver/impls/euler/euler.hxx +++ b/src/solver/impls/euler/euler.hxx @@ -64,6 +64,8 @@ private: /// Take a single step to calculate f1 void take_step(BoutReal curtime, BoutReal dt, Array& start, Array& result); + + BoutReal dump_at_time{-1.}; }; #endif // BOUT_KARNIADAKIS_SOLVER_H From 84bfcef2d10dc2dabf280c792a548519158414df Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 15 Apr 2024 11:25:59 +0200 Subject: [PATCH 20/71] Disable tracking once we are done --- include/bout/field3d.hxx | 7 +++++++ src/solver/impls/euler/euler.cxx | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index cfde9e5328..97118cb70a 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -299,6 +299,13 @@ public: /// Save all changes that, are done to the field, to tracking Field3D& enableTracking(const std::string& name, Options& tracking); + /// Disable tracking + Field3D& disableTracking(){ + tracking = nullptr; + tracking_state = 0; + return *this; + } + ///////////////////////////////////////////////////////// // Data access diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 45ba5ccdbf..227d7ba454 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -158,7 +158,7 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star run_rhs(curtime); if (dump_now) { Options& debug = *debug_ptr; - Mesh* mesh; + Mesh* mesh{nullptr}; for (auto& f : f3d) { debug[f.name] = *f.var; mesh = f.var->getMesh(); @@ -175,6 +175,9 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star bout::OptionsIO::create(outname)->write(debug); MPI_Barrier(BoutComm::get()); + for (auto& f : f3d) { + f.F_var->disableTracking(); + } } save_derivs(std::begin(result)); From 73265df7ebafd0a4d63763765977dd90cda2ce69 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 15 Apr 2024 11:27:07 +0200 Subject: [PATCH 21/71] Allow to dump every timestep with euler --- src/solver/impls/euler/euler.cxx | 14 ++++++++++---- src/solver/impls/euler/euler.hxx | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 227d7ba454..ded28984aa 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -144,7 +144,8 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star Array& result) { load_vars(std::begin(start)); - const bool dump_now = dump_at_time > 0 && std::abs(dump_at_time - curtime) < dt; + const bool dump_now = + (dump_at_time >= 0 && std::abs(dump_at_time - curtime) < dt) || dump_at_time < -3; std::unique_ptr debug_ptr; if (dump_now) { debug_ptr = std::make_unique(); @@ -152,6 +153,8 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star for (auto& f : f3d) { f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); setName(*f.var, f.name); + debug[fmt::format("pre_{:s}", f.name)] = *f.var; + f.var->allocate(); } } @@ -169,9 +172,12 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star debug["BOUT_VERSION"].force(bout::version::as_double); } - const std::string outname = fmt::format( - "{}/BOUT.debug.{}.nc", - Options::root()["datadir"].withDefault("data"), BoutComm::rank()); + const std::string outnumber = + dump_at_time < -3 ? fmt::format(".{}", debug_counter++) : ""; + const std::string outname = + fmt::format("{}/BOUT.debug{}.{}.nc", + Options::root()["datadir"].withDefault("data"), + outnumber, BoutComm::rank()); bout::OptionsIO::create(outname)->write(debug); MPI_Barrier(BoutComm::get()); diff --git a/src/solver/impls/euler/euler.hxx b/src/solver/impls/euler/euler.hxx index 4b6dc60a62..fc9b7f53bb 100644 --- a/src/solver/impls/euler/euler.hxx +++ b/src/solver/impls/euler/euler.hxx @@ -66,6 +66,7 @@ private: Array& result); BoutReal dump_at_time{-1.}; + int debug_counter{0}; }; #endif // BOUT_KARNIADAKIS_SOLVER_H From 8ff388aeb9f74c23fb6cc8a073565cc19276d268 Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Mon, 15 Apr 2024 09:30:12 +0000 Subject: [PATCH 22/71] Apply clang-format changes --- include/bout/field3d.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 97118cb70a..395e3201e4 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -300,7 +300,7 @@ public: Field3D& enableTracking(const std::string& name, Options& tracking); /// Disable tracking - Field3D& disableTracking(){ + Field3D& disableTracking() { tracking = nullptr; tracking_state = 0; return *this; From 6724e7548bf88a7824845a9caf1c77c49bef269b Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 9 Aug 2024 12:02:43 +0200 Subject: [PATCH 23/71] Dump also parallel fields by default --- src/solver/impls/pvode/pvode.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 9dce5d357f..66344f7cde 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -358,8 +358,8 @@ BoutReal PvodeSolver::run(BoutReal tout) { // Check return flag if (flag != SUCCESS) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); - CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; if (debug_on_failure) { + CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; if (f2d.empty() and v2d.empty() and v3d.empty()) { Options debug{}; using namespace std::string_literals; @@ -388,6 +388,9 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { debug[f.name] = *f.var; + if (f.var->hasParallelSlices()) { + saveParallel(debug, f.name, *f.var); + } } if (mesh != nullptr) { From 28212c2e97c725f20099fd302fb17efc86243c7b Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 9 Aug 2024 12:01:16 +0200 Subject: [PATCH 24/71] Also dump parallel fields --- src/solver/impls/euler/euler.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index ded28984aa..5477b5760b 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -163,7 +163,7 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star Options& debug = *debug_ptr; Mesh* mesh{nullptr}; for (auto& f : f3d) { - debug[f.name] = *f.var; + saveParallel(debug, f.name, *f.var); mesh = f.var->getMesh(); } From 9cf0fba6971c1c6367b3aee3c5d68f9bcf4121ed Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 9 Aug 2024 11:53:26 +0200 Subject: [PATCH 25/71] Clarify which div_par has been used --- src/mesh/coordinates.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 32774d6229..483b3e458c 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1601,7 +1601,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, f_B.yup(i) = f.yup(i) / Bxy_floc.yup(i); f_B.ydown(i) = f.ydown(i) / Bxy_floc.ydown(i); } - return setName(Bxy * Grad_par(f_B, outloc, method), "Div_par({:s})", f.name); + return setName(Bxy * Grad_par(f_B, outloc, method), "C:Div_par({:s})", f.name); } ///////////////////////////////////////////////////////// From 97b67e187149d5c7e6624ffd1222ef8d242d5270 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 9 Aug 2024 10:30:32 +0200 Subject: [PATCH 26/71] Expose tracking Useful for physics module to record additional data if the solver is failing --- include/bout/field3d.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 395e3201e4..0f227a8da3 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -510,6 +510,8 @@ public: int size() const override { return nx * ny * nz; }; + Options* getTracking() { return tracking; }; + private: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null int nx{-1}, ny{-1}, nz{-1}; From 77e08ec6f7e4e38978e1ec85218af8475991ce4b Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Tue, 22 Oct 2024 09:57:45 +0000 Subject: [PATCH 27/71] Apply clang-format changes --- src/solver/impls/pvode/pvode.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 66344f7cde..d4ac14fef2 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -388,9 +388,9 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { debug[f.name] = *f.var; - if (f.var->hasParallelSlices()) { - saveParallel(debug, f.name, *f.var); - } + if (f.var->hasParallelSlices()) { + saveParallel(debug, f.name, *f.var); + } } if (mesh != nullptr) { From ba6fc6cea816d0c2163dcbd3af4f64824a25f446 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 9 Aug 2024 10:32:17 +0200 Subject: [PATCH 28/71] Add simple interface to store parallel fields Just dumping the parallel slices does in general not work, as then collect discards that, especially if NYPE==ny --- include/bout/options.hxx | 3 +++ src/sys/options.cxx | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/bout/options.hxx b/include/bout/options.hxx index 839c847289..e1f5ae68fa 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -946,6 +946,9 @@ Tensor Options::as>(const Tensor& similar_t /// Convert \p value to string std::string toString(const Options& value); +/// Save the parallel fields +void saveParallel(Options& opt, const std::string name, const Field3D& tosave); + /// Output a stringified \p value to a stream /// /// This is templated to avoid implict casting: anything is diff --git a/src/sys/options.cxx b/src/sys/options.cxx index 49a81cfa88..71339b6089 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -306,6 +306,22 @@ void Options::assign<>(Tensor val, std::string source) { _set_no_check(std::move(val), std::move(source)); } +void saveParallel(Options& opt, const std::string name, const Field3D& tosave){ + ASSERT2(tosave.hasParallelSlices()); + opt[name] = tosave; + for (size_t i0=1 ; i0 <= tosave.numberParallelSlices(); ++i0) { + for (int i: {i0, -i0} ) { + Field3D tmp; + tmp.allocate(); + const auto& fpar = tosave.ynext(i); + for (auto j: fpar.getValidRegionWithDefault("RGN_NO_BOUNDARY")){ + tmp[j.yp(-i)] = fpar[j]; + } + opt[fmt::format("{}_y{:+d}", name, i)] = tmp; + } + } +} + namespace { /// Use FieldFactory to evaluate expression double parseExpression(const Options::ValueType& value, const Options* options, From 3c0d6a8f6a4d20bdee9d140b9f90af9432a6810c Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Tue, 22 Oct 2024 10:26:41 +0000 Subject: [PATCH 29/71] Apply clang-format changes --- src/sys/options.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sys/options.cxx b/src/sys/options.cxx index 71339b6089..1193deb013 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -306,16 +306,16 @@ void Options::assign<>(Tensor val, std::string source) { _set_no_check(std::move(val), std::move(source)); } -void saveParallel(Options& opt, const std::string name, const Field3D& tosave){ +void saveParallel(Options& opt, const std::string name, const Field3D& tosave) { ASSERT2(tosave.hasParallelSlices()); opt[name] = tosave; - for (size_t i0=1 ; i0 <= tosave.numberParallelSlices(); ++i0) { - for (int i: {i0, -i0} ) { + for (size_t i0 = 1; i0 <= tosave.numberParallelSlices(); ++i0) { + for (int i : {i0, -i0}) { Field3D tmp; tmp.allocate(); const auto& fpar = tosave.ynext(i); - for (auto j: fpar.getValidRegionWithDefault("RGN_NO_BOUNDARY")){ - tmp[j.yp(-i)] = fpar[j]; + for (auto j : fpar.getValidRegionWithDefault("RGN_NO_BOUNDARY")) { + tmp[j.yp(-i)] = fpar[j]; } opt[fmt::format("{}_y{:+d}", name, i)] = tmp; } From d0669cdcafa76bec00116abb2d934e05405eae35 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 22 Oct 2024 15:37:56 +0200 Subject: [PATCH 30/71] Do not use numberParallelSlices() --- src/sys/options.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sys/options.cxx b/src/sys/options.cxx index df1dee56f4..3f7a0c4071 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -338,9 +338,10 @@ void Options::assign<>(Tensor val, std::string source) { } void saveParallel(Options& opt, const std::string name, const Field3D& tosave) { - ASSERT2(tosave.hasParallelSlices()); opt[name] = tosave; - for (size_t i0 = 1; i0 <= tosave.numberParallelSlices(); ++i0) { + const size_t numberParallelSlices = + tosave.hasParallelSlices() ? 0 : tosave.getMesh()->ystart; + for (size_t i0 = 1; i0 <= numberParallelSlices; ++i0) { for (int i : {i0, -i0}) { Field3D tmp; tmp.allocate(); From 42fc8ff5350b8da32518a0bd449b8e3dc149bb9f Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:25:13 +0100 Subject: [PATCH 31/71] prefer const ref --- include/bout/options.hxx | 2 +- src/sys/options.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bout/options.hxx b/include/bout/options.hxx index e207c6b4d4..bc43bda3ef 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -991,7 +991,7 @@ Tensor Options::as>(const Tensor& similar_t std::string toString(const Options& value); /// Save the parallel fields -void saveParallel(Options& opt, const std::string name, const Field3D& tosave); +void saveParallel(Options& opt, const std::string& name, const Field3D& tosave); /// Output a stringified \p value to a stream /// diff --git a/src/sys/options.cxx b/src/sys/options.cxx index d49f014f25..e674667d7b 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -343,7 +343,7 @@ Options& Options::assign<>(Tensor val, std::string source) { return *this; } -void saveParallel(Options& opt, const std::string name, const Field3D& tosave) { +void saveParallel(Options& opt, const std::string& name, const Field3D& tosave) { opt[name] = tosave; const size_t numberParallelSlices = tosave.hasParallelSlices() ? 0 : tosave.getMesh()->ystart; From c9c13d4ee451234385be78ff3159b9a82a4ee3dd Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:25:53 +0100 Subject: [PATCH 32/71] Update for move of bout/version.hxx --- src/solver/impls/euler/euler.cxx | 1 + src/solver/impls/pvode/pvode.cxx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 5477b5760b..ce2a594cb8 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -1,6 +1,7 @@ #include "euler.hxx" +#include "bout/version.hxx" #include #include #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 5cc41e31c5..6db3b6ccfe 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -35,8 +35,8 @@ #include #include #include - -#include "bout/unused.hxx" +#include +#include #include // use CVSPGMR linear solver each internal step #include // contains the enum for types of preconditioning From ff93406d32ec28d84c6957191d787db5c25a16fb Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:26:07 +0100 Subject: [PATCH 33/71] Prefer auto --- src/solver/impls/pvode/pvode.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 6db3b6ccfe..3fc6b6866c 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -61,8 +61,8 @@ void pvode_load_data_f3d(const std::vector& evolve_bndrys, for (const auto& i2d : mesh->getRegion2D(bndry ? "RGN_BNDRY" : "RGN_NOBNDRY")) { for (int jz = 0; jz < nz; jz++) { // Loop over 3D variables - std::vector::const_iterator evolve_bndry = evolve_bndrys.begin(); - for (std::vector::iterator ff = ffs.begin(); ff != ffs.end(); ++ff) { + auto evolve_bndry = evolve_bndrys.cbegin(); + for (auto ff = ffs.begin(); ff != ffs.end(); ++ff) { if (bndry && !*evolve_bndry) { continue; } From a096cc5f812509857617529523727a96a17bc1ef Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:26:29 +0100 Subject: [PATCH 34/71] Avoid warning for 3d metrics --- src/physics/smoothing.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/smoothing.cxx b/src/physics/smoothing.cxx index 0a1391907f..036c475cd7 100644 --- a/src/physics/smoothing.cxx +++ b/src/physics/smoothing.cxx @@ -350,7 +350,7 @@ BoutReal Average_XY(const Field2D& var) { return Vol_Glb; } -BoutReal Vol_Integral(const Field2D& var) { +BoutReal Vol_Integral([[maybe_unused]] const Field2D& var) { #if BOUT_USE_METRIC_3D AUTO_TRACE(); throw BoutException("Vol_Intregral currently incompatible with 3D metrics"); From 27db46d503b98eb0fe8682595cd1cb7a115367d9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:29:36 +0100 Subject: [PATCH 35/71] Apply recommendations from code review * switch to std::weak_ptr * reorder branches in pvode debug * make track a trivial inline function * ensure _track template is only used for fields --- include/bout/field3d.hxx | 20 +++++--- src/field/field3d.cxx | 66 ++++++++++++++----------- src/solver/impls/euler/euler.cxx | 6 +-- src/solver/impls/pvode/pvode.cxx | 83 +++++++++++++++----------------- 4 files changed, 94 insertions(+), 81 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index d1b5a0813d..90ea7020db 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -293,11 +293,11 @@ public: /// Enable a special tracking mode for debugging /// Save all changes that, are done to the field, to tracking - Field3D& enableTracking(const std::string& name, Options& tracking); + Field3D& enableTracking(const std::string& name, std::weak_ptr tracking); /// Disable tracking Field3D& disableTracking() { - tracking = nullptr; + tracking.reset(); tracking_state = 0; return *this; } @@ -506,7 +506,7 @@ public: int size() const override { return nx * ny * nz; }; - Options* getTracking() { return tracking; }; + std::weak_ptr getTracking() { return tracking; }; private: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null @@ -525,11 +525,17 @@ private: std::optional regionID; int tracking_state{0}; - Options* tracking{nullptr}; + std::weak_ptr tracking; std::string selfname; - template - Options* track(const T& change, std::string operation); - Options* track(const BoutReal& change, std::string operation); + template + inline void track(const T& change, const std::string& operation) { + if (tracking_state != 0) { + _track(change, operation); + } + } + template > + void _track(const T& change, std::string operation); + void _track(const BoutReal& change, std::string operation); }; // Non-member overloaded operators diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 3807b54314..17571ea4c1 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -844,46 +844,56 @@ void Field3D::setRegion(const std::string& region_name) { regionID = fieldmesh->getRegionID(region_name); } -Field3D& Field3D::enableTracking(const std::string& name, Options& _tracking) { - tracking = &_tracking; +Field3D& Field3D::enableTracking(const std::string& name, + std::weak_ptr _tracking) { + tracking = _tracking; tracking_state = 1; selfname = name; return *this; } -template -Options* Field3D::track(const T& change, std::string operation) { - if (tracking != nullptr and tracking_state != 0) { - const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; - tracking->set(outname, change, "tracking"); - // Workaround for bug in gcc9.4 +template +void Field3D::_track(const T& change, std::string operation) { + if (tracking_state == 0) { + return; + } + auto locked = tracking.lock(); + if (locked == nullptr) { + return; + } + const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; + + locked->set(outname, change, "tracking"); + // Workaround for bug in gcc9.4 #if BOUT_USE_TRACK - const std::string changename = change.name; + const std::string changename = change.name; #endif - (*tracking)[outname].setAttributes({ + (*locked)[outname].setAttributes({ {"operation", operation}, #if BOUT_USE_TRACK - {"rhs.name", changename}, + {"rhs.name", changename}, #endif - }); - return &(*tracking)[outname]; - } - return nullptr; + }); } -template Options* Field3D::track(const Field3D&, std::string); -template Options* Field3D::track(const Field2D&, std::string); -template Options* Field3D::track(const FieldPerp&, std::string); +template void +Field3D::_track>(const Field3D&, + std::string); +template void Field3D::_track(const Field2D&, std::string); +template void Field3D::_track<>(const FieldPerp&, std::string); -Options* Field3D::track(const BoutReal& change, std::string operation) { - if (tracking and tracking_state) { - const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; - tracking->set(outname, change, "tracking"); - (*tracking)[outname].setAttributes({ - {"operation", operation}, - {"rhs.name", "BR"}, - }); - return &(*tracking)[outname]; +void Field3D::_track(const BoutReal& change, std::string operation) { + if (tracking_state == 0) { + return; } - return nullptr; + auto locked = tracking.lock(); + if (locked == nullptr) { + return; + } + const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; + locked->set(outname, change, "tracking"); + (*locked)[outname].setAttributes({ + {"operation", operation}, + {"rhs.name", "BoutReal"}, + }); } diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index ce2a594cb8..110331eeb1 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -147,12 +147,12 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star load_vars(std::begin(start)); const bool dump_now = (dump_at_time >= 0 && std::abs(dump_at_time - curtime) < dt) || dump_at_time < -3; - std::unique_ptr debug_ptr; + std::shared_ptr debug_ptr; if (dump_now) { - debug_ptr = std::make_unique(); + debug_ptr = std::make_shared(); Options& debug = *debug_ptr; for (auto& f : f3d) { - f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); + f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug_ptr); setName(*f.var, f.name); debug[fmt::format("pre_{:s}", f.name)] = *f.var; f.var->allocate(); diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 3fc6b6866c..4815f0153b 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -360,56 +360,53 @@ BoutReal PvodeSolver::run(BoutReal tout) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); if (debug_on_failure) { CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; - if (f2d.empty() and v2d.empty() and v3d.empty()) { - Options debug{}; - using namespace std::string_literals; - Mesh* mesh{}; - for (const auto& prefix : {"pre_"s, "residuum_"s}) { - std::vector list_of_fields{}; - std::vector evolve_bndrys{}; - for (const auto& f : f3d) { - mesh = f.var->getMesh(); - Field3D to_load{0., mesh}; - to_load.allocate(); - to_load.setLocation(f.location); - debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; - list_of_fields.push_back(to_load); - evolve_bndrys.push_back(f.evolve_bndry); - } - pvode_load_data_f3d(evolve_bndrys, list_of_fields, - prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); + if (!(f2d.empty() and v2d.empty() and v3d.empty())) { + output_warn.write("debug_on_failure is currently only supported for Field3Ds"); + return -1.0; + } + auto debug_ptr = std::make_shared(); + Options& debug = *debug_ptr; + using namespace std::string_literals; + Mesh* mesh{}; + for (const auto& prefix : {"pre_"s, "residuum_"s}) { + std::vector list_of_fields{}; + std::vector evolve_bndrys{}; + for (const auto& f : f3d) { + mesh = f.var->getMesh(); + Field3D to_load{0., mesh}; + to_load.allocate(); + to_load.setLocation(f.location); + debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; + list_of_fields.push_back(to_load); + evolve_bndrys.push_back(f.evolve_bndry); } + pvode_load_data_f3d(evolve_bndrys, list_of_fields, + prefix == "pre_"s ? udata : N_VDATA(cv_mem->cv_acor)); + } - for (auto& f : f3d) { - f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug); - setName(*f.var, f.name); - } - run_rhs(simtime); + for (auto& f : f3d) { + f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug_ptr); + setName(*f.var, f.name); + } + run_rhs(simtime); - for (auto& f : f3d) { - debug[f.name] = *f.var; - if (f.var->hasParallelSlices()) { - saveParallel(debug, f.name, *f.var); - } - } + for (auto& f : f3d) { + saveParallel(debug, f.name, *f.var); + } - if (mesh != nullptr) { - mesh->outputVars(debug); - debug["BOUT_VERSION"].force(bout::version::as_double); - } + if (mesh != nullptr) { + mesh->outputVars(debug); + debug["BOUT_VERSION"].force(bout::version::as_double); + } - const std::string outname = - fmt::format("{}/BOUT.debug.{}.nc", - Options::root()["datadir"].withDefault("data"), - BoutComm::rank()); + const std::string outname = fmt::format( + "{}/BOUT.debug.{}.nc", + Options::root()["datadir"].withDefault("data"), BoutComm::rank()); - bout::OptionsIO::create(outname)->write(debug); - MPI_Barrier(BoutComm::get()); - } else { - output_warn.write("debug_on_failure is currently only supported for Field3Ds"); - } + bout::OptionsIO::create(outname)->write(debug); + MPI_Barrier(BoutComm::get()); } - return (-1.0); + return -1.0; } return simtime; From 24610c3682c43934e6560c73130d2030da234218 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 16 Jan 2025 12:29:52 +0100 Subject: [PATCH 36/71] Explain purpose of variables --- include/bout/field3d.hxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 90ea7020db..8866f17b49 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -524,8 +524,11 @@ private: /// RegionID over which the field is valid std::optional regionID; + /// counter for tracking, to assign unique names to the variable names int tracking_state{0}; std::weak_ptr tracking; + // name is changed if we assign to the variable, while selfname is a + // non-changing copy that is used for the variable names in the dump files std::string selfname; template inline void track(const T& change, const std::string& operation) { From f6db2df5dc97f1f2047e3328503f8728a337977b Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:30:30 +0000 Subject: [PATCH 37/71] Apply clang-format changes --- src/field/field3d.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 17571ea4c1..1eeb0dd344 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -869,9 +869,9 @@ void Field3D::_track(const T& change, std::string operation) { const std::string changename = change.name; #endif (*locked)[outname].setAttributes({ - {"operation", operation}, + {"operation", operation}, #if BOUT_USE_TRACK - {"rhs.name", changename}, + {"rhs.name", changename}, #endif }); } From d1c137f01f0f53cdefcdbb9789c43ef384da30ab Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 2 Jul 2024 15:38:01 +0200 Subject: [PATCH 38/71] Add option to disable tracking --- include/bout/field3d.hxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 8866f17b49..ac2baf56ba 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -302,6 +302,13 @@ public: return *this; } + /// Disable tracking + Field3D& disableTracking() { + tracking = nullptr; + tracking_state = 0; + return *this; + } + ///////////////////////////////////////////////////////// // Data access From ee8a9d6b5ac711a78507c292757f14e57c69b0ef Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:01:45 +0000 Subject: [PATCH 39/71] Apply clang-format changes --- include/bout/invertable_operator.hxx | 4 ++-- src/bout++.cxx | 2 +- src/field/field3d.cxx | 4 ++-- src/solver/impls/arkode/arkode.cxx | 6 ++---- src/solver/impls/snes/snes.hxx | 14 +++++++------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/bout/invertable_operator.hxx b/include/bout/invertable_operator.hxx index fe139986be..99f7d9b675 100644 --- a/include/bout/invertable_operator.hxx +++ b/include/bout/invertable_operator.hxx @@ -575,7 +575,7 @@ public: }; #endif // PETSC -}; // namespace inversion -}; // namespace bout +}; // namespace inversion +}; // namespace bout #endif // HEADER GUARD diff --git a/src/bout++.cxx b/src/bout++.cxx index 7f23cf5f91..4e9e37fe8d 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -84,7 +84,7 @@ const char DEFAULT_DIR[] = "data"; // Define S_ISDIR if not defined by system headers (that is, MSVC) // Taken from https://github.com/curl/curl/blob/e59540139a398dc70fde6aec487b19c5085105af/lib/curl_setup.h#L748-L751 #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) -#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifdef _MSC_VER diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 1eeb0dd344..17571ea4c1 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -869,9 +869,9 @@ void Field3D::_track(const T& change, std::string operation) { const std::string changename = change.name; #endif (*locked)[outname].setAttributes({ - {"operation", operation}, + {"operation", operation}, #if BOUT_USE_TRACK - {"rhs.name", changename}, + {"rhs.name", changename}, #endif }); } diff --git a/src/solver/impls/arkode/arkode.cxx b/src/solver/impls/arkode/arkode.cxx index 23883cc043..02f2cb7b81 100644 --- a/src/solver/impls/arkode/arkode.cxx +++ b/src/solver/impls/arkode/arkode.cxx @@ -229,8 +229,7 @@ int ArkodeSolver::init() { throw BoutException("ARKodeSetUserData failed\n"); } - if (ARKodeSetLinear(arkode_mem, static_cast(set_linear)) - != ARK_SUCCESS) { + if (ARKodeSetLinear(arkode_mem, static_cast(set_linear)) != ARK_SUCCESS) { throw BoutException("ARKodeSetLinear failed\n"); } @@ -415,8 +414,7 @@ int ArkodeSolver::init() { if (hasPreconditioner()) { output.write("\tUsing user-supplied preconditioner\n"); - if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) - != ARKLS_SUCCESS) { + if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) != ARKLS_SUCCESS) { throw BoutException("ARKodeSetPreconditioner failed\n"); } } else { diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index 17050ad775..f695ba3718 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -121,9 +121,9 @@ private: Vec x1; ///< Previous solution BoutReal time1{-1.0}; ///< Time of previous solution - SNES snes; ///< SNES context - Mat Jmf; ///< Matrix Free Jacobian - Mat Jfd; ///< Finite Difference Jacobian + SNES snes; ///< SNES context + Mat Jmf; ///< Matrix Free Jacobian + Mat Jfd; ///< Finite Difference Jacobian MatFDColoring fdcoloring{nullptr}; ///< Matrix coloring context ///< Jacobian evaluation @@ -135,10 +135,10 @@ private: std::string pc_hypre_type; ///< Hypre preconditioner type std::string line_search_type; ///< Line search type - bool matrix_free; ///< Use matrix free Jacobian - bool matrix_free_operator; ///< Use matrix free Jacobian in the operator? - int lag_jacobian; ///< Re-use Jacobian - bool use_coloring; ///< Use matrix coloring + bool matrix_free; ///< Use matrix free Jacobian + bool matrix_free_operator; ///< Use matrix free Jacobian in the operator? + int lag_jacobian; ///< Re-use Jacobian + bool use_coloring; ///< Use matrix coloring bool jacobian_recalculated; ///< Flag set when Jacobian is recalculated bool prune_jacobian; ///< Remove small elements in the Jacobian? From e684304083bc5594f85bea2fed5a03ab42987a53 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 20 Nov 2025 14:19:39 +0100 Subject: [PATCH 40/71] Forward f to avoid copy --- include/bout/field.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index fb74dcb93d..9e576f938f 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -690,7 +690,7 @@ inline T setName(T&& f, const std::string& name, Types... args) { #if BOUT_USE_TRACK f.name = fmt::format(name, args...); #endif - return f; + return std::forward(f); } #endif /* FIELD_H */ From b75d020bc10ca6b6dc86418118a575a8d70a2b5f Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 24 Nov 2025 10:58:50 +0100 Subject: [PATCH 41/71] Add missing header from clang-tidy --- include/bout/field.hxx | 1 + include/bout/field3d.hxx | 4 ++++ src/field/field3d.cxx | 4 ++++ src/field/gen_fieldops.py | 15 +++++++++------ src/field/generated_fieldops.cxx | 15 +++++++++------ src/mesh/coordinates.cxx | 1 + src/solver/impls/euler/euler.cxx | 6 ++++++ src/solver/impls/pvode/pvode.cxx | 5 +++++ 8 files changed, 39 insertions(+), 12 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 9e576f938f..2d813bb275 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -36,6 +36,7 @@ class Field; #include "bout/bout_types.hxx" #include "bout/boutcomm.hxx" #include "bout/boutexception.hxx" +#include "bout/build_defines.hxx" #include "bout/field_data.hxx" #include "bout/msg_stack.hxx" #include "bout/region.hxx" diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 039c085cfd..4dff626d7b 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -33,11 +33,15 @@ class Field3D; #include "bout/field2d.hxx" #include "bout/fieldperp.hxx" #include "bout/region.hxx" +#include "bout/traits.hxx" +#include #include +#include #include class Mesh; +class Options; /// Class for 3D X-Y-Z scalar fields /*! diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index cf7c339e39..3b4765e063 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -31,6 +31,8 @@ #include #include +#include +#include #include "bout/parallel_boundary_op.hxx" #include "bout/parallel_boundary_region.hxx" @@ -47,6 +49,8 @@ #include #include +#include "fmt/format.h" + /// Constructor Field3D::Field3D(Mesh* localmesh, CELL_LOC location_in, DirectionTypes directions_in) : Field(localmesh, location_in, directions_in) { diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 29631ff7aa..b6f99549d2 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -65,12 +65,15 @@ def smart_open(filename, mode="r"): ) header = """// This file is autogenerated - see gen_fieldops.py -#include -#include -#include -#include -#include -#include +#include "bout/build_defines.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/globals.hxx" +#include "bout/interpolation.hxx" +#include "bout/mesh.hxx" +#include "bout/region.hxx" + +#include "fmt/format.h" """ diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 3495d87dbc..f37a870c74 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -1,10 +1,13 @@ // This file is autogenerated - see gen_fieldops.py -#include -#include -#include -#include -#include -#include +#include "bout/build_defines.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/globals.hxx" +#include "bout/interpolation.hxx" +#include "bout/mesh.hxx" +#include "bout/region.hxx" + +#include "fmt/format.h" // Provide the C++ wrapper for multiplication of Field3D and Field3D Field3D operator*(const Field3D& lhs, const Field3D& rhs) { diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3f67a5dc72..e805df00f2 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 110331eeb1..7d81b979a2 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -4,11 +4,17 @@ #include "bout/version.hxx" #include #include +#include "bout/field.hxx" +#include #include #include +#include #include +#include + #include +#include #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 4815f0153b..339508c385 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,11 @@ #include // contains the enum for types of preconditioning #include // band preconditioner function prototypes +#include "fmt/format.h" + #include +#include +#include using namespace pvode; From b824cfc15e4312d2eb10edee56144b0492e6b45f Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 24 Nov 2025 10:59:47 +0100 Subject: [PATCH 42/71] Apply more clang-tidy suggestions --- include/bout/field3d.hxx | 2 +- src/field/field3d.cxx | 2 +- src/solver/impls/pvode/pvode.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 4dff626d7b..537613eda8 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -540,7 +540,7 @@ private: // non-changing copy that is used for the variable names in the dump files std::string selfname; template - inline void track(const T& change, const std::string& operation) { + void track(const T& change, const std::string& operation) { if (tracking_state != 0) { _track(change, operation); } diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 3b4765e063..7ece06a454 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -875,7 +875,7 @@ void Field3D::setRegion(const std::string& region_name) { Field3D& Field3D::enableTracking(const std::string& name, std::weak_ptr _tracking) { - tracking = _tracking; + tracking = std::move(_tracking); tracking_state = 1; selfname = name; return *this; diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 339508c385..a7b5f2e242 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -364,7 +364,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { if (flag != SUCCESS) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); if (debug_on_failure) { - CVodeMemRec* cv_mem = (CVodeMem)cvode_mem; + CVodeMemRec* cv_mem = static_cast(cvode_mem); if (!(f2d.empty() and v2d.empty() and v3d.empty())) { output_warn.write("debug_on_failure is currently only supported for Field3Ds"); return -1.0; From 90815fa149704ae97124880df0f1b15e840619c6 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 24 Nov 2025 11:04:14 +0100 Subject: [PATCH 43/71] Add more headers explicitly --- src/solver/impls/pvode/pvode.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index a7b5f2e242..601cfc2448 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include // use CVSPGMR linear solver each internal step #include // contains the enum for types of preconditioning #include // band preconditioner function prototypes @@ -47,6 +49,7 @@ #include #include +#include #include using namespace pvode; From 69457b855d00aadec2463b77853cc8f42eef17a6 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:08:34 +0000 Subject: [PATCH 44/71] Apply clang-format changes --- src/solver/impls/euler/euler.cxx | 2 +- src/solver/impls/pvode/pvode.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 7d81b979a2..a4804590dc 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -1,10 +1,10 @@ #include "euler.hxx" +#include "bout/field.hxx" #include "bout/version.hxx" #include #include -#include "bout/field.hxx" #include #include #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 601cfc2448..f25c5bd9f2 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -47,10 +47,10 @@ #include "fmt/format.h" -#include +#include #include +#include #include -#include using namespace pvode; From b265c907dcae25dd0f326e82fcd805328328674e Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 24 Nov 2025 11:12:30 +0100 Subject: [PATCH 45/71] Remove duplicate definition --- include/bout/field3d.hxx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 537613eda8..fad4815b92 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -306,13 +306,6 @@ public: return *this; } - /// Disable tracking - Field3D& disableTracking() { - tracking = nullptr; - tracking_state = 0; - return *this; - } - ///////////////////////////////////////////////////////// // Data access From 9c47bb8ae02c23d7027c210979cbb16ed3ae76a5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 24 Nov 2025 11:16:24 +0100 Subject: [PATCH 46/71] Add more headers explicitly --- src/solver/impls/pvode/pvode.cxx | 1 + src/sys/options.cxx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index f25c5bd9f2..6bd218e86b 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/src/sys/options.cxx b/src/sys/options.cxx index b3238bf758..ada63bd526 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -22,6 +22,7 @@ #include #include +#include #include #include #include From 02cc7d17e806a0617069987c426f9bbdc2f4f9fd Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:17:09 +0000 Subject: [PATCH 47/71] Apply clang-format changes --- src/solver/impls/pvode/pvode.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 6bd218e86b..2b83d4f155 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -35,8 +35,8 @@ #include #include #include -#include #include +#include #include #include #include From cb0d3f12061424e81c199272ff6e9f8589be35f0 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 21 Jan 2026 12:12:12 +0100 Subject: [PATCH 48/71] Add backtrace to tracked operations This avoids mostly the need for annotations using BOUT_USE_TRACK. setName could thus be dropped. --- src/field/field3d.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index a2ca5aad5e..00cdd8982f 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include "bout/parallel_boundary_op.hxx" #include "bout/parallel_boundary_region.hxx" @@ -859,6 +860,9 @@ void Field3D::_track(const T& change, std::string operation) { const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; locked->set(outname, change, "tracking"); + + const std::string trace = cpptrace::generate_trace().to_string(); + // Workaround for bug in gcc9.4 #if BOUT_USE_TRACK const std::string changename = change.name; @@ -868,6 +872,7 @@ void Field3D::_track(const T& change, std::string operation) { #if BOUT_USE_TRACK {"rhs.name", changename}, #endif + {"trace", trace}, }); } @@ -885,10 +890,12 @@ void Field3D::_track(const BoutReal& change, std::string operation) { if (locked == nullptr) { return; } + const std::string trace = cpptrace::generate_trace().to_string(); const std::string outname{fmt::format("track_{:s}_{:d}", selfname, tracking_state++)}; locked->set(outname, change, "tracking"); (*locked)[outname].setAttributes({ {"operation", operation}, {"rhs.name", "BoutReal"}, + {"trace", trace}, }); } From f2ed814db206d92c729980d4ad9d317ff3ebcf59 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 29 Jan 2026 09:07:41 +0000 Subject: [PATCH 49/71] Apply clang-format changes --- src/field/field3d.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 00cdd8982f..c669516399 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -31,9 +31,9 @@ #include #include +#include #include #include -#include #include "bout/parallel_boundary_op.hxx" #include "bout/parallel_boundary_region.hxx" From e3f8923b4692a4d969127147cf4b57b00ea72aab Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 29 Jan 2026 10:25:08 +0100 Subject: [PATCH 50/71] Apply clang-format suggestions --- src/solver/impls/euler/euler.cxx | 4 +++- src/solver/impls/pvode/pvode.cxx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index f33d07f9d3..4b7a1bc029 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -1,6 +1,8 @@ - #include "euler.hxx" +#include +#include + #include "bout/field.hxx" #include "bout/version.hxx" #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index a0a0efa377..59f7b3867f 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -64,7 +64,7 @@ namespace { void pvode_load_data_f3d(const std::vector& evolve_bndrys, std::vector& ffs, const BoutReal* udata) { int p = 0; - Mesh* mesh = ffs[0].getMesh(); + const Mesh* mesh = ffs[0].getMesh(); const int nz = mesh->LocalNz; for (const auto& bndry : {true, false}) { for (const auto& i2d : mesh->getRegion2D(bndry ? "RGN_BNDRY" : "RGN_NOBNDRY")) { @@ -366,7 +366,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { if (flag != SUCCESS) { output_error.write("ERROR CVODE step failed, flag = {:d}\n", flag); if (debug_on_failure) { - CVodeMemRec* cv_mem = static_cast(cvode_mem); + const CVodeMemRec* cv_mem = static_cast(cvode_mem); if (!(f2d.empty() and v2d.empty() and v3d.empty())) { output_warn.write("debug_on_failure is currently only supported for Field3Ds"); return -1.0; From 873c94f89117d1af0aa35a7781bdec4f26293ff5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 29 Jan 2026 10:33:14 +0100 Subject: [PATCH 51/71] Apply clang-format suggestions --- src/solver/impls/euler/euler.cxx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 4b7a1bc029..a430f0a585 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -1,15 +1,16 @@ #include "euler.hxx" -#include -#include - -#include "bout/field.hxx" -#include "bout/version.hxx" +#include +#include #include #include #include #include +#include +#include +#include + EulerSolver::EulerSolver(Options* options) : Solver(options), mxstep((*options)["mxstep"] .doc("Maximum number of steps between outputs") From 7e5c3112667544350007225f58998a1782214561 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 29 Jan 2026 09:39:23 +0000 Subject: [PATCH 52/71] Apply clang-format changes --- src/solver/impls/euler/euler.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index a430f0a585..78721d2e8f 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -1,15 +1,15 @@ #include "euler.hxx" -#include -#include #include #include +#include #include #include +#include #include -#include #include +#include EulerSolver::EulerSolver(Options* options) : Solver(options), mxstep((*options)["mxstep"] From e5f2d373ff594776d6f878f598647fc5905551ba Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 2 Feb 2026 11:49:51 +0100 Subject: [PATCH 53/71] do not TRACK names --- src/field/gen_fieldops.jinja | 7 ------- src/field/gen_fieldops.py | 15 ++++++--------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index 58b1ae28ba..5476242d50 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -61,10 +61,6 @@ } {% endif %} -#if BOUT_USE_TRACK - {{out.name}}.name = fmt::format("{:s} {{operator}} {:s}", {{'"BR"' if lhs == "BoutReal" else lhs.name + ".name"}} - , {{'"BR"' if rhs == "BoutReal" else rhs.name + ".name"}}); -#endif checkData({{out.name}}); return {{out.name}}; } @@ -136,9 +132,6 @@ {% if lhs == "Field3D" %} track(rhs, "operator{{operator}}="); {% endif %} -#if BOUT_USE_TRACK - name = fmt::format("{:s} {{operator}}= {:s}", this->name, {{'"BR"' if rhs == "BoutReal" else rhs.name + ".name"}}); -#endif checkData(*this); diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 30c8101e97..3e07d6fec4 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -64,15 +64,12 @@ def smart_open(filename, mode="r"): ) header = """// This file is autogenerated - see gen_fieldops.py -#include "bout/build_defines.hxx" -#include "bout/field2d.hxx" -#include "bout/field3d.hxx" -#include "bout/globals.hxx" -#include "bout/interpolation.hxx" -#include "bout/mesh.hxx" -#include "bout/region.hxx" - -#include "fmt/format.h" +#include +#include +#include +#include +#include +#include """ From 751abc463ec6f9dd53eb3cc334b15cbf16ba7bc1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 2 Feb 2026 11:50:05 +0100 Subject: [PATCH 54/71] Remove setName again --- include/bout/field.hxx | 16 ---------------- src/mesh/coordinates.cxx | 4 ++-- src/solver/impls/euler/euler.cxx | 1 - src/solver/impls/pvode/pvode.cxx | 1 - 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index c188a0d8eb..4e41aa3632 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -35,7 +35,6 @@ class Field; #include "bout/bout_types.hxx" #include "bout/boutcomm.hxx" #include "bout/boutexception.hxx" -#include "bout/build_defines.hxx" #include "bout/field_data.hxx" #include "bout/region.hxx" #include "bout/traits.hxx" @@ -668,19 +667,4 @@ inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { #undef FIELD_FUNC -template , class... Types> -inline void setName(T& f, const std::string& name, Types... args) { -#if BOUT_USE_TRACK - f.name = fmt::format(name, args...); -#endif -} - -template , class... Types> -inline T setName(T&& f, const std::string& name, Types... args) { -#if BOUT_USE_TRACK - f.name = fmt::format(name, args...); -#endif - return std::forward(f); -} - #endif /* FIELD_H */ diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index ade7ac158a..b8b0f9ea55 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1531,7 +1531,7 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return setName(::DDY(var, outloc, method) * invSg(), "Grad_par({:s})", var.name); + return ::DDY(var, outloc, method) * invSg(); } ///////////////////////////////////////////////////////// @@ -1590,7 +1590,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, f_B.yup(i) = f.yup(i) / Bxy_floc.yup(i); f_B.ydown(i) = f.ydown(i) / Bxy_floc.ydown(i); } - return setName(Bxy * Grad_par(f_B, outloc, method), "C:Div_par({:s})", f.name); + return xy * Grad_par(f_B, outloc, method); } ///////////////////////////////////////////////////////// diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 78721d2e8f..6bdceab516 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -150,7 +150,6 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star Options& debug = *debug_ptr; for (auto& f : f3d) { f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug_ptr); - setName(*f.var, f.name); debug[fmt::format("pre_{:s}", f.name)] = *f.var; f.var->allocate(); } diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 59f7b3867f..4cc90af8fd 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -393,7 +393,6 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { f.F_var->enableTracking(fmt::format("ddt_{:s}", f.name), debug_ptr); - setName(*f.var, f.name); } run_rhs(simtime); From 3cc061bb7181cd2cd42f74f39fe864c08d4f3a90 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 2 Feb 2026 11:51:42 +0100 Subject: [PATCH 55/71] Update generated source code --- src/field/generated_fieldops.cxx | 327 +------------------------------ 1 file changed, 6 insertions(+), 321 deletions(-) diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index f37a870c74..24bfde425c 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -1,13 +1,10 @@ // This file is autogenerated - see gen_fieldops.py -#include "bout/build_defines.hxx" -#include "bout/field2d.hxx" -#include "bout/field3d.hxx" -#include "bout/globals.hxx" -#include "bout/interpolation.hxx" -#include "bout/mesh.hxx" -#include "bout/region.hxx" - -#include "fmt/format.h" +#include +#include +#include +#include +#include +#include // Provide the C++ wrapper for multiplication of Field3D and Field3D Field3D operator*(const Field3D& lhs, const Field3D& rhs) { @@ -23,9 +20,6 @@ Field3D operator*(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -49,9 +43,6 @@ Field3D& Field3D::operator*=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } track(rhs, "operator*="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -76,9 +67,6 @@ Field3D operator/(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -102,9 +90,6 @@ Field3D& Field3D::operator/=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } track(rhs, "operator/="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -129,9 +114,6 @@ Field3D operator+(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -155,9 +137,6 @@ Field3D& Field3D::operator+=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } track(rhs, "operator+="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -182,9 +161,6 @@ Field3D operator-(const Field3D& lhs, const Field3D& rhs) { result[index] = lhs[index] - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -208,9 +184,6 @@ Field3D& Field3D::operator-=(const Field3D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } track(rhs, "operator-="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -240,9 +213,6 @@ Field3D operator*(const Field3D& lhs, const Field2D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -269,9 +239,6 @@ Field3D& Field3D::operator*=(const Field2D& rhs) { } track(rhs, "operator*="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -302,9 +269,6 @@ Field3D operator/(const Field3D& lhs, const Field2D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -332,9 +296,6 @@ Field3D& Field3D::operator/=(const Field2D& rhs) { } track(rhs, "operator/="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -364,9 +325,6 @@ Field3D operator+(const Field3D& lhs, const Field2D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -393,9 +351,6 @@ Field3D& Field3D::operator+=(const Field2D& rhs) { } track(rhs, "operator+="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -425,9 +380,6 @@ Field3D operator-(const Field3D& lhs, const Field2D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -454,9 +406,6 @@ Field3D& Field3D::operator-=(const Field2D& rhs) { } track(rhs, "operator-="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif checkData(*this); @@ -483,9 +432,6 @@ FieldPerp operator*(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -506,9 +452,6 @@ FieldPerp operator/(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -529,9 +472,6 @@ FieldPerp operator+(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -552,9 +492,6 @@ FieldPerp operator-(const Field3D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -572,9 +509,6 @@ Field3D operator*(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -595,9 +529,6 @@ Field3D& Field3D::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } track(rhs, "operator*="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, "BR"); -#endif checkData(*this); @@ -622,9 +553,6 @@ Field3D operator/(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -646,9 +574,6 @@ Field3D& Field3D::operator/=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= tmp; } track(rhs, "operator/="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, "BR"); -#endif checkData(*this); @@ -672,9 +597,6 @@ Field3D operator+(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -695,9 +617,6 @@ Field3D& Field3D::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } track(rhs, "operator+="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, "BR"); -#endif checkData(*this); @@ -721,9 +640,6 @@ Field3D operator-(const Field3D& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -744,9 +660,6 @@ Field3D& Field3D::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } track(rhs, "operator-="); -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, "BR"); -#endif checkData(*this); @@ -776,9 +689,6 @@ Field3D operator*(const Field2D& lhs, const Field3D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -802,9 +712,6 @@ Field3D operator/(const Field2D& lhs, const Field3D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -828,9 +735,6 @@ Field3D operator+(const Field2D& lhs, const Field3D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -854,9 +758,6 @@ Field3D operator-(const Field2D& lhs, const Field3D& rhs) { } } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -873,9 +774,6 @@ Field2D operator*(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -892,10 +790,6 @@ Field2D& Field2D::operator*=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -916,9 +810,6 @@ Field2D operator/(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -935,10 +826,6 @@ Field2D& Field2D::operator/=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -959,9 +846,6 @@ Field2D operator+(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -978,10 +862,6 @@ Field2D& Field2D::operator+=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1002,9 +882,6 @@ Field2D operator-(const Field2D& lhs, const Field2D& rhs) { result[index] = lhs[index] - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1021,10 +898,6 @@ Field2D& Field2D::operator-=(const Field2D& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1049,9 +922,6 @@ FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1072,9 +942,6 @@ FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1095,9 +962,6 @@ FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1118,9 +982,6 @@ FieldPerp operator-(const Field2D& lhs, const FieldPerp& rhs) { result[index] = lhs[base_ind] - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1136,9 +997,6 @@ Field2D operator*(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1154,10 +1012,6 @@ Field2D& Field2D::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1178,9 +1032,6 @@ Field2D operator/(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1197,10 +1048,6 @@ Field2D& Field2D::operator/=(const BoutReal rhs) { const auto tmp = 1.0 / rhs; BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= tmp; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1220,9 +1067,6 @@ Field2D operator+(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1238,10 +1082,6 @@ Field2D& Field2D::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1261,9 +1101,6 @@ Field2D operator-(const Field2D& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1279,10 +1116,6 @@ Field2D& Field2D::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1307,9 +1140,6 @@ FieldPerp operator*(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] * rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1332,10 +1162,6 @@ FieldPerp& FieldPerp::operator*=(const Field3D& rhs) { (*this)[index] *= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1360,9 +1186,6 @@ FieldPerp operator/(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] / rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1385,10 +1208,6 @@ FieldPerp& FieldPerp::operator/=(const Field3D& rhs) { (*this)[index] /= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1413,9 +1232,6 @@ FieldPerp operator+(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] + rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1438,10 +1254,6 @@ FieldPerp& FieldPerp::operator+=(const Field3D& rhs) { (*this)[index] += rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1466,9 +1278,6 @@ FieldPerp operator-(const FieldPerp& lhs, const Field3D& rhs) { result[index] = lhs[index] - rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1491,10 +1300,6 @@ FieldPerp& FieldPerp::operator-=(const Field3D& rhs) { (*this)[index] -= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1519,9 +1324,6 @@ FieldPerp operator*(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] * rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1544,10 +1346,6 @@ FieldPerp& FieldPerp::operator*=(const Field2D& rhs) { (*this)[index] *= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1572,9 +1370,6 @@ FieldPerp operator/(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] / rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1597,10 +1392,6 @@ FieldPerp& FieldPerp::operator/=(const Field2D& rhs) { (*this)[index] /= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1625,9 +1416,6 @@ FieldPerp operator+(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] + rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1650,10 +1438,6 @@ FieldPerp& FieldPerp::operator+=(const Field2D& rhs) { (*this)[index] += rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1678,9 +1462,6 @@ FieldPerp operator-(const FieldPerp& lhs, const Field2D& rhs) { result[index] = lhs[index] - rhs[base_ind]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1703,10 +1484,6 @@ FieldPerp& FieldPerp::operator-=(const Field2D& rhs) { (*this)[index] -= rhs[base_ind]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1727,9 +1504,6 @@ FieldPerp operator*(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1746,10 +1520,6 @@ FieldPerp& FieldPerp::operator*=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1770,9 +1540,6 @@ FieldPerp operator/(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1789,10 +1556,6 @@ FieldPerp& FieldPerp::operator/=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1813,9 +1576,6 @@ FieldPerp operator+(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1832,10 +1592,6 @@ FieldPerp& FieldPerp::operator+=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1856,9 +1612,6 @@ FieldPerp operator-(const FieldPerp& lhs, const FieldPerp& rhs) { result[index] = lhs[index] - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); -#endif checkData(result); return result; } @@ -1875,10 +1628,6 @@ FieldPerp& FieldPerp::operator-=(const FieldPerp& rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, rhs.name); -#endif - checkData(*this); } else { @@ -1898,9 +1647,6 @@ FieldPerp operator*(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] * rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1916,10 +1662,6 @@ FieldPerp& FieldPerp::operator*=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} *= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1940,9 +1682,6 @@ FieldPerp operator/(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] * tmp; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1958,10 +1697,6 @@ FieldPerp& FieldPerp::operator/=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} /= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -1981,9 +1716,6 @@ FieldPerp operator+(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] + rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -1999,10 +1731,6 @@ FieldPerp& FieldPerp::operator+=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} += {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -2022,9 +1750,6 @@ FieldPerp operator-(const FieldPerp& lhs, const BoutReal rhs) { result[index] = lhs[index] - rhs; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); -#endif checkData(result); return result; } @@ -2040,10 +1765,6 @@ FieldPerp& FieldPerp::operator-=(const BoutReal rhs) { BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } -#if BOUT_USE_TRACK - name = fmt::format("{:s} -= {:s}", this->name, "BR"); -#endif - checkData(*this); } else { @@ -2065,9 +1786,6 @@ Field3D operator*(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2085,9 +1803,6 @@ Field3D operator/(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2105,9 +1820,6 @@ Field3D operator+(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2125,9 +1837,6 @@ Field3D operator-(const BoutReal lhs, const Field3D& rhs) { result[index] = lhs - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2143,9 +1852,6 @@ Field2D operator*(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2161,9 +1867,6 @@ Field2D operator/(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2179,9 +1882,6 @@ Field2D operator+(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2197,9 +1897,6 @@ Field2D operator-(const BoutReal lhs, const Field2D& rhs) { result[index] = lhs - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2215,9 +1912,6 @@ FieldPerp operator*(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs * rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2233,9 +1927,6 @@ FieldPerp operator/(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs / rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2251,9 +1942,6 @@ FieldPerp operator+(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs + rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); -#endif checkData(result); return result; } @@ -2269,9 +1957,6 @@ FieldPerp operator-(const BoutReal lhs, const FieldPerp& rhs) { result[index] = lhs - rhs[index]; } -#if BOUT_USE_TRACK - result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); -#endif checkData(result); return result; } From 52301380586fdbf890f620c04f689b08d89a6c34 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:52:25 +0000 Subject: [PATCH 56/71] [bot] Apply format changes --- examples/blob2d/blob_velocity.py | 154 ++++++------ examples/boutpp/simulation.py | 5 +- examples/conduction-snb/fit_temperature.py | 24 +- examples/conduction-snb/sinusoid.py | 30 ++- examples/conduction-snb/step.py | 31 ++- examples/conduction/generate.py | 4 +- examples/eigen-box/eigenvals.py | 35 +-- examples/elm-pb/Python/2dprofile.py | 91 ++++--- examples/elm-pb/Python/analysis.py | 16 +- examples/elm-pb/Python/elm_size.py | 179 +++++++------ examples/elm-pb/Python/fftall.py | 9 +- examples/elm-pb/Python/fftall2.py | 10 +- examples/elm-pb/Python/grate.py | 9 +- examples/elm-pb/Python/grate2.py | 45 ++-- examples/elm-pb/Python/plotcollapse.py | 47 ++-- examples/elm-pb/Python/plotmode.py | 93 ++++--- examples/elm-pb/Python/plotmode2.py | 94 ++++--- examples/elm-pb/Python/plotphase.py | 45 ++-- examples/elm-pb/Python/polslice.py | 26 +- examples/elm-pb/Python/post.py | 142 +++++++---- examples/elm-pb/Python/read_elmsize.py | 46 ++-- examples/elm-pb/Python/showpolslice.py | 36 +-- examples/elm-pb/Python/sprofiles.py | 41 +-- examples/elm-pb/runexample.py | 28 ++- examples/fci-wave/compare-density.py | 45 ++-- examples/finite-volume/diffusion/mms.py | 14 +- examples/finite-volume/fluid/mms.py | 20 +- examples/laplace-petsc3d/plotcheck.py | 16 +- examples/orszag-tang/generate.py | 116 +++++---- .../performance/bracket/scaling_parser.py | 5 +- .../performance/ddx/new_scaling_parser.py | 32 +-- .../performance/ddy/new_scaling_parser.py | 32 +-- .../performance/ddz/new_scaling_parser.py | 32 +-- .../performance/iterator/scaling_parser.py | 5 +- examples/staggered_grid/generate.py | 6 +- examples/subsampling/show.py | 10 +- examples/wave-slab/generate.py | 2 +- .../figure_creators/LaplacianMatrices.ipynb | 236 ++++++++++-------- .../bout_runners_folder_structure.py | 97 +++---- tests/MMS/advection/runtest | 2 +- 40 files changed, 1039 insertions(+), 871 deletions(-) diff --git a/examples/blob2d/blob_velocity.py b/examples/blob2d/blob_velocity.py index d044946320..6de0937d0f 100644 --- a/examples/blob2d/blob_velocity.py +++ b/examples/blob2d/blob_velocity.py @@ -3,96 +3,100 @@ import pickle try: - from past.utils import old_div + from past.utils import old_div except ImportError: - def old_div(a,b): - return a/b - -def blob_velocity(n,**kwargs): - - from boututils import calculus as Calc - # Calculate blob velocity in normalized time and normalized grid spacing - # - # Input: Blob density as a 3D vector in the form n[t,x,z] where t is time and x,z are the perpendicular spatial coordinates - # - # Keywords: - # - # type='peak' -> Calculate velocity of the peak density - # type='COM' -> Calculate centre of mass velocity - # Index=True -> return indices used to create velocity - # - # Default: Peak velocity with no index returning - - size = n.shape - - try: - v_type = kwargs['type'] - except: - v_type = 'peak' #Default to peak velocity calculation - try: - return_index = kwargs['Index'] - except: - return_index = False #Default to no index returning - - - if v_type == 'peak': - x = np.zeros(size[0]) - z = np.zeros(size[0]) - for i in np.arange(size[0]): - nmax,nmin = np.amax((n[i,:,:])),np.amin((n[i,:,:])) - xpos,zpos = np.where(n[i,:,:]==nmax) - x[i] = xpos[0] - z[i] = zpos[0] - - if v_type == 'COM': - x = np.zeros(size[0]) - z = np.zeros(size[0]) - for i in np.arange(size[0]): - data = n[i,:,:] - n[0,0,0] #use corner cell rather than nmin - ntot = np.sum(data[:,:]) - - z[i] = old_div(np.sum(np.sum(data[:,:],axis=0)*(np.arange(size[2]))),ntot) - x[i] = old_div(np.sum(np.sum(data[:,:],axis=1)*(np.arange(size[1]))),ntot) - - vx = Calc.deriv(x) - vz = Calc.deriv(z) - - if return_index: - return vx,vz,x,z - else: - return vx,vz - - - -data='data' + def old_div(a, b): + return a / b + + +def blob_velocity(n, **kwargs): + from boututils import calculus as Calc + # Calculate blob velocity in normalized time and normalized grid spacing + # + # Input: Blob density as a 3D vector in the form n[t,x,z] where t is time and x,z are the perpendicular spatial coordinates + # + # Keywords: + # + # type='peak' -> Calculate velocity of the peak density + # type='COM' -> Calculate centre of mass velocity + # Index=True -> return indices used to create velocity + # + # Default: Peak velocity with no index returning + + size = n.shape + + try: + v_type = kwargs["type"] + except: + v_type = "peak" # Default to peak velocity calculation + try: + return_index = kwargs["Index"] + except: + return_index = False # Default to no index returning + + if v_type == "peak": + x = np.zeros(size[0]) + z = np.zeros(size[0]) + for i in np.arange(size[0]): + nmax, nmin = np.amax((n[i, :, :])), np.amin((n[i, :, :])) + xpos, zpos = np.where(n[i, :, :] == nmax) + x[i] = xpos[0] + z[i] = zpos[0] + + if v_type == "COM": + x = np.zeros(size[0]) + z = np.zeros(size[0]) + for i in np.arange(size[0]): + data = n[i, :, :] - n[0, 0, 0] # use corner cell rather than nmin + ntot = np.sum(data[:, :]) + + z[i] = old_div( + np.sum(np.sum(data[:, :], axis=0) * (np.arange(size[2]))), ntot + ) + x[i] = old_div( + np.sum(np.sum(data[:, :], axis=1) * (np.arange(size[1]))), ntot + ) + + vx = Calc.deriv(x) + vz = Calc.deriv(z) + + if return_index: + return vx, vz, x, z + else: + return vx, vz + + +data = "data" if True: - import sys - if len(sys.argv) > 1: - data=sys.argv[1] + import sys + + if len(sys.argv) > 1: + data = sys.argv[1] -n = collect('n', path=data, info=False) +n = collect("n", path=data, info=False) -vx,vy,xx,yy = blob_velocity(n[:,:,0,:],type='COM',Index=True) +vx, vy, xx, yy = blob_velocity(n[:, :, 0, :], type="COM", Index=True) -f = open('Velocity.dat','wb') -pickle.dump(vx,f) +f = open("Velocity.dat", "wb") +pickle.dump(vx, f) f.close() -f = open('Position.dat','wb') -pickle.dump(xx,f) +f = open("Position.dat", "wb") +pickle.dump(xx, f) f.close() -f = open('Velocity.dat','rb') +f = open("Velocity.dat", "rb") vx = pickle.load(f) f.close() try: - import matplotlib.pyplot as plt - plt.plot(vx) - plt.show() + import matplotlib.pyplot as plt + + plt.plot(vx) + plt.show() except ImportError: - pass + pass diff --git a/examples/boutpp/simulation.py b/examples/boutpp/simulation.py index 1b57ff8b33..9948bd9b03 100755 --- a/examples/boutpp/simulation.py +++ b/examples/boutpp/simulation.py @@ -3,12 +3,13 @@ bc.init("mesh:n=48") + class Model(bc.PhysicsModel): - def init(self,restart): + def init(self, restart): self.dens = bc.create3D("sin(x)") self.solve_for(n=self.dens) - def rhs(self,time): + def rhs(self, time): self.dens.ddt(bc.DDX(self.dens)) diff --git a/examples/conduction-snb/fit_temperature.py b/examples/conduction-snb/fit_temperature.py index 1e7f3ddf94..81faa9cf93 100644 --- a/examples/conduction-snb/fit_temperature.py +++ b/examples/conduction-snb/fit_temperature.py @@ -3,23 +3,31 @@ import matplotlib.pyplot as plt Te_ref = np.loadtxt("temperature.csv", delimiter=",") -Te_ref[:,0] *= 1e-4 # Convert X axis to m +Te_ref[:, 0] *= 1e-4 # Convert X axis to m + def te_function(ypos, mid, wwid, w0, w1, w2, Tmax, Tmin, clip=False): - width = w0 + ((ypos - mid)*w1 + (ypos - mid)**2 * w2) * np.exp(-((ypos - mid)/wwid)**2) + width = w0 + ((ypos - mid) * w1 + (ypos - mid) ** 2 * w2) * np.exp( + -(((ypos - mid) / wwid) ** 2) + ) if clip: width = np.clip(width, 1e-10, None) - return Tmax - 0.5 * (1 + np.tanh((ypos - mid)/width)) * (Tmax - Tmin) + return Tmax - 0.5 * (1 + np.tanh((ypos - mid) / width)) * (Tmax - Tmin) + -popt, pcov = optimize.curve_fit(te_function, Te_ref[:,0], Te_ref[:,1], - p0 = [2.2e-4, 1e-4, 1e-4, 0.0, 0.0, 0.960, 0.190]) +popt, pcov = optimize.curve_fit( + te_function, + Te_ref[:, 0], + Te_ref[:, 1], + p0=[2.2e-4, 1e-4, 1e-4, 0.0, 0.0, 0.960, 0.190], +) print(popt) -xfit = np.linspace(Te_ref[0,0], Te_ref[-1,0], 100) +xfit = np.linspace(Te_ref[0, 0], Te_ref[-1, 0], 100) -plt.plot(xfit, te_function(xfit, *popt, clip=True), '-k') -plt.plot(Te_ref[:,0], Te_ref[:,1], 'or') +plt.plot(xfit, te_function(xfit, *popt, clip=True), "-k") +plt.plot(Te_ref[:, 0], Te_ref[:, 1], "or") plt.show() diff --git a/examples/conduction-snb/sinusoid.py b/examples/conduction-snb/sinusoid.py index 10c81923a3..439530383e 100644 --- a/examples/conduction-snb/sinusoid.py +++ b/examples/conduction-snb/sinusoid.py @@ -11,7 +11,7 @@ build_and_log("Sinusoidal SNB") # Electron temperature in eV -Telist = 10 ** np.linspace(0,3,20) +Telist = 10 ** np.linspace(0, 3, 20) # Electron density in m^-3 Ne = 1e20 @@ -19,29 +19,30 @@ # Length of the domain in m length = 1.0 -c = 299792458 -mu0 = 4.e-7*np.pi -e0 = 1/(c*c*mu0) +c = 299792458 +mu0 = 4.0e-7 * np.pi +e0 = 1 / (c * c * mu0) qe = 1.602176634e-19 me = 9.10938356e-31 -thermal_speed = np.sqrt(2.*qe * Telist / me) -Y = (qe**2 / (e0 * me))**2 / (4 * np.pi) +thermal_speed = np.sqrt(2.0 * qe * Telist / me) +Y = (qe**2 / (e0 * me)) ** 2 / (4 * np.pi) coulomb_log = 6.6 - 0.5 * np.log(Ne * 1e-20) + 1.5 * np.log(Telist) -lambda_ee_T = thermal_speed**4 / (Y * Ne * coulomb_log) +lambda_ee_T = thermal_speed**4 / (Y * Ne * coulomb_log) beta_max_list = [5, 10, 20, 40] -colors = ['k','b','g','r'] +colors = ["k", "b", "g", "r"] ngroups_list = [20, 40, 80] -syms = ['x', 'o', 'D'] +syms = ["x", "o", "D"] for beta_max, color in zip(beta_max_list, colors): for ngroups, sym in zip(ngroups_list, syms): - flux_ratio = [] for Te in Telist: - cmd = "./conduction-snb \"Te={0}+0.01*sin(y)\" Ne={1} mesh:length={2} snb:beta_max={3} snb:ngroups={4}".format(Te, Ne, length, beta_max, ngroups) + cmd = './conduction-snb "Te={0}+0.01*sin(y)" Ne={1} mesh:length={2} snb:beta_max={3} snb:ngroups={4}'.format( + Te, Ne, length, beta_max, ngroups + ) # Run the case s, out = launch_safe(cmd, nproc=1, mthread=1, pipe=True) @@ -54,7 +55,12 @@ flux_ratio.append(div_q[ind] / div_q_SH[ind]) - plt.plot(lambda_ee_T / length, flux_ratio, '-'+sym+color, label=r"$\beta_{{max}}={0}, N_g={1}$".format(beta_max,ngroups)) + plt.plot( + lambda_ee_T / length, + flux_ratio, + "-" + sym + color, + label=r"$\beta_{{max}}={0}, N_g={1}$".format(beta_max, ngroups), + ) plt.legend() plt.xlabel(r"$\lambda_{ee,T} / L$") diff --git a/examples/conduction-snb/step.py b/examples/conduction-snb/step.py index 1f8933e66b..63a13149f4 100644 --- a/examples/conduction-snb/step.py +++ b/examples/conduction-snb/step.py @@ -3,7 +3,7 @@ # # Uses a step in the temperature, intended for comparison to VFP results -length = 6e-4 # Domain length in m +length = 6e-4 # Domain length in m qe = 1.602176634e-19 @@ -40,37 +40,37 @@ # Read reference values Te_ref = np.loadtxt("temperature.csv", delimiter=",") -Te_ref[:,0] *= 1e-4 # Convert X axis to m +Te_ref[:, 0] *= 1e-4 # Convert X axis to m SH_ref = np.loadtxt("spitzer-harm.csv", delimiter=",") -SH_ref[:,0] *= 1e-4 +SH_ref[:, 0] *= 1e-4 SNB_ref = np.loadtxt("snb.csv", delimiter=",") -SNB_ref[:,0] *= 1e-4 +SNB_ref[:, 0] *= 1e-4 VFP_ref = np.loadtxt("vfp.csv", delimiter=",") -VFP_ref[:,0] *= 1e-4 +VFP_ref[:, 0] *= 1e-4 ######################################### fig, ax1 = plt.subplots() -color='tab:red' +color = "tab:red" ax1.plot(position, Te * 1e-3, color=color, label="Te") -ax1.plot(Te_ref[:,0], Te_ref[:,1], color=color, marker="o", label="Reference Te") +ax1.plot(Te_ref[:, 0], Te_ref[:, 1], color=color, marker="o", label="Reference Te") ax1.set_xlabel("position [m]") ax1.set_ylabel("Electron temperature [keV]", color=color) -ax1.set_ylim(0,1) -ax1.tick_params(axis='y', colors=color) +ax1.set_ylim(0, 1) +ax1.tick_params(axis="y", colors=color) ax2 = ax1.twinx() -ax2.plot(position, q_SH * 1e-4, '-k', label="Spitzer-Harm") -ax2.plot(SH_ref[:,0], SH_ref[:,1], '--k', label="Reference SH") +ax2.plot(position, q_SH * 1e-4, "-k", label="Spitzer-Harm") +ax2.plot(SH_ref[:, 0], SH_ref[:, 1], "--k", label="Reference SH") -ax2.plot(position, q * 1e-4, '-b', label="SNB") -ax2.plot(SNB_ref[:,0], SNB_ref[:,1], '--b', label="Reference SNB") +ax2.plot(position, q * 1e-4, "-b", label="SNB") +ax2.plot(SNB_ref[:, 0], SNB_ref[:, 1], "--b", label="Reference SNB") -ax2.plot(VFP_ref[:,0], VFP_ref[:,1], '--g', label="Reference VFP") +ax2.plot(VFP_ref[:, 0], VFP_ref[:, 1], "--g", label="Reference VFP") ax2.set_ylabel("Heat flux W/cm^2") ax2.set_ylim(bottom=0.0) @@ -78,8 +78,7 @@ plt.legend() fig.tight_layout() -plt.xlim(0,3.5e-4) +plt.xlim(0, 3.5e-4) plt.savefig("snb-step.png") plt.show() - diff --git a/examples/conduction/generate.py b/examples/conduction/generate.py index 7138026898..4a2a2acfc0 100755 --- a/examples/conduction/generate.py +++ b/examples/conduction/generate.py @@ -4,9 +4,9 @@ # Generate an input mesh # -from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries +from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries -nx = 5 # Minimum is 5: 2 boundary, one evolved +nx = 5 # Minimum is 5: 2 boundary, one evolved ny = 64 # Minimum 5. Should be divisible by number of processors (so powers of 2 nice) f = DataFile() diff --git a/examples/eigen-box/eigenvals.py b/examples/eigen-box/eigenvals.py index 7b52fc60f2..5a71aabfc6 100755 --- a/examples/eigen-box/eigenvals.py +++ b/examples/eigen-box/eigenvals.py @@ -27,7 +27,8 @@ def plot_eigenvals(eigenvalues, eigenvectors=None): raise ValueError("Expecting eigenvectors to be 2D") if eigenvectors.shape[0] != len(eigenvalues): raise ValueError( - "First dimension of eigenvectors must match length of eigenvalues") + "First dimension of eigenvectors must match length of eigenvalues" + ) # If no eigenvectors supplied, only plot eigenvalues, otherwise # eigenvalues and eigenvectors @@ -44,18 +45,18 @@ def plot_eigenvals(eigenvalues, eigenvectors=None): range_r = amax(eigs_r) - amin(eigs_r) range_i = amax(eigs_i) - amin(eigs_i) - ax[0].plot(eigs_r, eigs_i, 'x') + ax[0].plot(eigs_r, eigs_i, "x") ax[0].set_xlabel("Real component") ax[0].set_ylabel("Imaginary component") ax[0].set_title("Eigenvalue") - overplot, = ax[0].plot([], [], 'ok') + (overplot,) = ax[0].plot([], [], "ok") if eigenvectors is not None: # Add a eigenvectors plot - vector_r, = ax[1].plot([], [], '-k', label="Real") - vector_i, = ax[1].plot([], [], '-r', label="Imag") - ax[1].legend(loc='upper right') + (vector_r,) = ax[1].plot([], [], "-k", label="Real") + (vector_i,) = ax[1].plot([], [], "-r", label="Imag") + ax[1].legend(loc="upper right") ax[1].set_xlabel("X") ax[1].set_ylabel("Amplitude") ax[1].set_title("Eigenvector") @@ -68,33 +69,33 @@ def onclick(event): # Find closest eigenvectors point, but stretch axes so # real and imaginary components are weighted equally - if(range_r == 0): - dist = ((eigs_i - event.ydata)/range_i)**2 - elif(range_i == 0): - dist = ((eigs_r - event.xdata)/range_r)**2 + if range_r == 0: + dist = ((eigs_i - event.ydata) / range_i) ** 2 + elif range_i == 0: + dist = ((eigs_r - event.xdata) / range_r) ** 2 else: - dist = ((eigs_r - event.xdata)/range_r)**2 + \ - ((eigs_i - event.ydata)/range_i)**2 + dist = ((eigs_r - event.xdata) / range_r) ** 2 + ( + (eigs_i - event.ydata) / range_i + ) ** 2 ind = argmin(dist) # Update the highlight plot overplot.set_data([eigs_r[ind]], [eigs_i[ind]]) - print("Eigenvalue number: %d (%e,%e)" % - (ind, eigs_r[ind], eigs_i[ind])) + print("Eigenvalue number: %d (%e,%e)" % (ind, eigs_r[ind], eigs_i[ind])) if eigenvectors is not None: # Update plots nx = eigenvectors.shape[1] - vector_r.set_data(arange(nx), eigenvectors[2*ind, :]) - vector_i.set_data(arange(nx), eigenvectors[2*ind+1, :]) + vector_r.set_data(arange(nx), eigenvectors[2 * ind, :]) + vector_i.set_data(arange(nx), eigenvectors[2 * ind + 1, :]) ax[1].relim() ax[1].autoscale_view() fig.canvas.draw() - fig.canvas.mpl_connect('button_press_event', onclick) + fig.canvas.mpl_connect("button_press_event", onclick) plt.show() diff --git a/examples/elm-pb/Python/2dprofile.py b/examples/elm-pb/Python/2dprofile.py index 5bb01972f9..e95709ab5b 100644 --- a/examples/elm-pb/Python/2dprofile.py +++ b/examples/elm-pb/Python/2dprofile.py @@ -4,81 +4,92 @@ import numpy as np import matplotlib.pyplot as plt from boututils.datafile import DataFile -from matplotlib.ticker import FixedFormatter, FormatStrFormatter, AutoLocator, AutoMinorLocator +from matplotlib.ticker import ( + FixedFormatter, + FormatStrFormatter, + AutoLocator, + AutoMinorLocator, +) with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: g = {v: f.read(v) for v in f.keys()} -majorLocator = AutoLocator() -majorFormatter = FormatStrFormatter('%3.0e') -minorLocator = AutoMinorLocator() -Fm = FixedFormatter(['0','$1 \\times 10^4$','$2 \\times 10^4$','$3 \\times 10^4$','$4 \\times 10^4$']) -Fm2 = FixedFormatter(['0','$2 \\times 10^5$','$4 \\times 10^5$','$6 \\times 10^5$']) - -bxy=g.get('Bxy') -p=g.get('pressure') -jpar0=g.get('Jpar0') -psixy=g.get('psixy') -btxy=g.get('Btxy') -shiftangle=g.get('ShiftAngle') - -nx=g.get('nx') -ny=g.get('ny') +majorLocator = AutoLocator() +majorFormatter = FormatStrFormatter("%3.0e") +minorLocator = AutoMinorLocator() +Fm = FixedFormatter( + [ + "0", + "$1 \\times 10^4$", + "$2 \\times 10^4$", + "$3 \\times 10^4$", + "$4 \\times 10^4$", + ] +) +Fm2 = FixedFormatter(["0", "$2 \\times 10^5$", "$4 \\times 10^5$", "$6 \\times 10^5$"]) + +bxy = g.get("Bxy") +p = g.get("pressure") +jpar0 = g.get("Jpar0") +psixy = g.get("psixy") +btxy = g.get("Btxy") +shiftangle = g.get("ShiftAngle") + +nx = g.get("nx") +ny = g.get("ny") q = np.zeros((nx, ny)) for i in range(ny): - q[:,i] = old_div(- shiftangle, (2 * np.pi)) - - + q[:, i] = old_div(-shiftangle, (2 * np.pi)) -xarr = psixy[:,0] +xarr = psixy[:, 0] xarr = old_div((xarr + 0.854856), (0.854856 + 0.0760856)) -fig=plt.figure() -plt.plot(xarr,q[:,32]) -plt.xlabel('normalized $\psi$', fontsize=25) -plt.ylabel('$q$',rotation='horizontal',fontsize=25) +fig = plt.figure() +plt.plot(xarr, q[:, 32]) +plt.xlabel("normalized $\psi$", fontsize=25) +plt.ylabel("$q$", rotation="horizontal", fontsize=25) fig.set_tight_layout(True) fig, ax1 = plt.subplots() -ax1.plot(xarr, p[:,32], 'r-', markevery=1, linewidth=3) -ax1.set_xlabel('normalized $\psi$',fontsize=25) +ax1.plot(xarr, p[:, 32], "r-", markevery=1, linewidth=3) +ax1.set_xlabel("normalized $\psi$", fontsize=25) # Make the y-axis label and tick labels match the line color. -ax1.set_ylabel('Pressure [Pa]', color='k',fontsize=25) +ax1.set_ylabel("Pressure [Pa]", color="k", fontsize=25) -#set y limit -ax1.set_ylim(0,40000,10000) +# set y limit +ax1.set_ylim(0, 40000, 10000) -#define ticks# +# define ticks# ax1.yaxis.set_ticks(np.arange(0, 40000, 10000)) -#ax1.yaxis.set_major_locator(majorLocator) -#ax1.yaxis.set_major_formatter(majorFormatter) +# ax1.yaxis.set_major_locator(majorLocator) +# ax1.yaxis.set_major_formatter(majorFormatter) ax1.yaxis.set_major_formatter(Fm) -#for the minor ticks, use no labels; default NullFormatter +# for the minor ticks, use no labels; default NullFormatter ax1.xaxis.set_minor_locator(AutoMinorLocator()) ax1.yaxis.set_minor_locator(AutoMinorLocator(10)) -#format tick labels +# format tick labels for tl in ax1.get_yticklabels(): - tl.set_color('k') + tl.set_color("k") ax2 = ax1.twinx() s2 = -jpar0 -ax2.plot(xarr, s2[:,32], 'r-',markevery=1,linewidth=3) -ax2.set_ylabel('$J_\parallel [A/m^2]$', color='k',fontsize=25) -ax2.set_ylim(0,600000) +ax2.plot(xarr, s2[:, 32], "r-", markevery=1, linewidth=3) +ax2.set_ylabel("$J_\parallel [A/m^2]$", color="k", fontsize=25) +ax2.set_ylim(0, 600000) ax2.yaxis.set_ticks(np.arange(0, 600000, 200000)) ax2.yaxis.set_major_formatter(Fm2) for tl in ax2.get_yticklabels(): - tl.set_color('k') + tl.set_color("k") fig.set_tight_layout(True) @@ -86,4 +97,4 @@ plt.show() -#plt.savefig('2d.png', transparent=True) +# plt.savefig('2d.png', transparent=True) diff --git a/examples/elm-pb/Python/analysis.py b/examples/elm-pb/Python/analysis.py index 4faf85f8ce..0e4a3acfdd 100644 --- a/examples/elm-pb/Python/analysis.py +++ b/examples/elm-pb/Python/analysis.py @@ -6,24 +6,24 @@ import pylab as plt from boutdata.collect import collect -path='./data/' -var=collect('P', path=path) +path = "./data/" +var = collect("P", path=path) -dcvar=np.mean(var, axis=3) -rmsvar=np.sqrt(np.mean(var**2,axis=3)-dcvar**2) +dcvar = np.mean(var, axis=3) +rmsvar = np.sqrt(np.mean(var**2, axis=3) - dcvar**2) plt.figure() -plt.plot(rmsvar[:,34,32]) +plt.plot(rmsvar[:, 34, 32]) plt.show(block=False) -fvar=np.fft.rfft(var,axis=3) +fvar = np.fft.rfft(var, axis=3) plt.figure() -plt.plot(abs(fvar[:,34,32,1:10])) +plt.plot(abs(fvar[:, 34, 32, 1:10])) plt.show(block=False) plt.figure() -plt.semilogy(abs(fvar[:,34,32,1:7])) +plt.semilogy(abs(fvar[:, 34, 32, 1:7])) plt.show(block=False) plt.show() diff --git a/examples/elm-pb/Python/elm_size.py b/examples/elm-pb/Python/elm_size.py index 0d5c105870..6ad2ed6a0d 100644 --- a/examples/elm-pb/Python/elm_size.py +++ b/examples/elm-pb/Python/elm_size.py @@ -4,87 +4,126 @@ from past.utils import old_div import numpy as np -def elm_size(dcp,p0,uedge,xmin=None,xmax=None,yind=None,Bbar=None): - - lis=[dcp,p0,uedge] - if np.size(lis) != 3 : + +def elm_size(dcp, p0, uedge, xmin=None, xmax=None, yind=None, Bbar=None): + lis = [dcp, p0, uedge] + if np.size(lis) != 3: print("lack of parameters") return 0 - - if xmin == None : xmin=0 - if xmax == None : xmax=327 - if yind == None : yind=63 # choose the poloidal location for 1D size - if Bbar == None : Bbar=1.992782 # the normalized magnetic field + if xmin == None: + xmin = 0 + if xmax == None: + xmax = 327 + if yind == None: + yind = 63 # choose the poloidal location for 1D size + if Bbar == None: + Bbar = 1.992782 # the normalized magnetic field - mydcp=dcp - myp0=p0 - g=uedge + mydcp = dcp + myp0 = p0 + g = uedge PI = 3.1415926 - MU0 = 4.0e-7*PI + MU0 = 4.0e-7 * PI - s=np.shape(mydcp) + s = np.shape(mydcp) - if np.ndim(mydcp) != 3 : + if np.ndim(mydcp) != 3: print("dcp should be 3D(t,x,y)") - - - nt=s[0] - nx=s[1] - ny=s[2] - - Dtheta=g['dy'] #using correct poloidal angle - psixy=g['psixy'] - R=g['Rxy'] - Bp=g['Bpxy'] - hthe=g['hthe'] - - Dpsi=np.zeros((nx,ny)) - Dpsi[0,:]=psixy[1,:]-psixy[0,:] - Dpsi[nx-1,:]=psixy[nx-1,:]-psixy[nx-2,:] - for i in range(1,nx-2): - Dpsi[i,:]=old_div((psixy[i+1,:]-psixy[i-1,:]),2) - - - Ddcp1=np.zeros(nt) - Ddcp2=np.zeros(nt) - Ddcp3=np.zeros(nt) - Tp01=0. - Tp02=0. - Tp03=0. - - for t in range(nt) : - Ddcp3[t]=2.0*PI*np.sum(mydcp[t,xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/Bp[xmin:xmax,:]) - Ddcp2[t]=np.sum(mydcp[t,xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/(R[xmin:xmax,:]*Bp[xmin:xmax,:])) - Ddcp1[t]=np.sum(mydcp[t,xmin:xmax,yind]*Dpsi[xmin:xmax,yind]/(R[xmin:xmax,yind]*Bp[xmin:xmax,yind])) - - - Tp03=2.0*PI*np.sum(myp0[xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/Bp[xmin:xmax,:]) - Tp02=np.sum(myp0[xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/(R[xmin:xmax,:]*Bp[xmin:xmax,:])) - Tp01=np.sum(myp0[xmin:xmax,yind]*Dpsi[xmin:xmax,yind]/(R[xmin:xmax,yind]*Bp[xmin:xmax,yind])) - - s1=np.zeros(nt) - s2=np.zeros(nt) - s3=np.zeros(nt) - E_loss=np.zeros(nt) - - s1=old_div(-Ddcp1,Tp01) #1D elm size - s2=old_div(-Ddcp2,Tp02) #2D elm size - s3=old_div(-Ddcp3,Tp03) #3D elm size - - E_loss=-Ddcp3*(0.5*Bbar*Bbar/MU0) #energy loss, unit J - E_total=Tp03*(0.5*Bbar*Bbar/MU0) #total energy, unit J + + nt = s[0] + nx = s[1] + ny = s[2] + + Dtheta = g["dy"] # using correct poloidal angle + psixy = g["psixy"] + R = g["Rxy"] + Bp = g["Bpxy"] + hthe = g["hthe"] + + Dpsi = np.zeros((nx, ny)) + Dpsi[0, :] = psixy[1, :] - psixy[0, :] + Dpsi[nx - 1, :] = psixy[nx - 1, :] - psixy[nx - 2, :] + for i in range(1, nx - 2): + Dpsi[i, :] = old_div((psixy[i + 1, :] - psixy[i - 1, :]), 2) + + Ddcp1 = np.zeros(nt) + Ddcp2 = np.zeros(nt) + Ddcp3 = np.zeros(nt) + Tp01 = 0.0 + Tp02 = 0.0 + Tp03 = 0.0 + + for t in range(nt): + Ddcp3[t] = ( + 2.0 + * PI + * np.sum( + mydcp[t, xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / Bp[xmin:xmax, :] + ) + ) + Ddcp2[t] = np.sum( + mydcp[t, xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / (R[xmin:xmax, :] * Bp[xmin:xmax, :]) + ) + Ddcp1[t] = np.sum( + mydcp[t, xmin:xmax, yind] + * Dpsi[xmin:xmax, yind] + / (R[xmin:xmax, yind] * Bp[xmin:xmax, yind]) + ) + + Tp03 = ( + 2.0 + * PI + * np.sum( + myp0[xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / Bp[xmin:xmax, :] + ) + ) + Tp02 = np.sum( + myp0[xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / (R[xmin:xmax, :] * Bp[xmin:xmax, :]) + ) + Tp01 = np.sum( + myp0[xmin:xmax, yind] + * Dpsi[xmin:xmax, yind] + / (R[xmin:xmax, yind] * Bp[xmin:xmax, yind]) + ) + + s1 = np.zeros(nt) + s2 = np.zeros(nt) + s3 = np.zeros(nt) + E_loss = np.zeros(nt) + + s1 = old_div(-Ddcp1, Tp01) # 1D elm size + s2 = old_div(-Ddcp2, Tp02) # 2D elm size + s3 = old_div(-Ddcp3, Tp03) # 3D elm size + + E_loss = -Ddcp3 * (0.5 * Bbar * Bbar / MU0) # energy loss, unit J + E_total = Tp03 * (0.5 * Bbar * Bbar / MU0) # total energy, unit J class ELM: pass - elmsize=ELM() - elmsize.s1=s1 - elmsize.s2=s2 - elmsize.s3=s3 - elmsize.E_loss=E_loss - elmsize.E_total=E_total + + elmsize = ELM() + elmsize.s1 = s1 + elmsize.s2 = s2 + elmsize.s3 = s3 + elmsize.E_loss = E_loss + elmsize.E_total = E_total return elmsize - - diff --git a/examples/elm-pb/Python/fftall.py b/examples/elm-pb/Python/fftall.py index e0a4385764..c6d5b87ded 100644 --- a/examples/elm-pb/Python/fftall.py +++ b/examples/elm-pb/Python/fftall.py @@ -2,8 +2,7 @@ from numpy import * from scipy.io import readsav -print('Calculating P..') -a=transpose(readsav('phi.idl.dat')['phi']) -fa=fft.fft(a,axis=2) -save('fp',fa) - +print("Calculating P..") +a = transpose(readsav("phi.idl.dat")["phi"]) +fa = fft.fft(a, axis=2) +save("fp", fa) diff --git a/examples/elm-pb/Python/fftall2.py b/examples/elm-pb/Python/fftall2.py index d864f356d0..64b08c437a 100644 --- a/examples/elm-pb/Python/fftall2.py +++ b/examples/elm-pb/Python/fftall2.py @@ -2,9 +2,9 @@ from numpy import * from boutdata.collect import collect -path='./data/' -data=collect('P',path=path) +path = "./data/" +data = collect("P", path=path) -print('Saving P..') -fa=fft.fft(data,axis=3) -save('fp',rollaxis(fa,0,4)) +print("Saving P..") +fa = fft.fft(data, axis=3) +save("fp", rollaxis(fa, 0, 4)) diff --git a/examples/elm-pb/Python/grate.py b/examples/elm-pb/Python/grate.py index 003f38ff8e..65d6da6449 100644 --- a/examples/elm-pb/Python/grate.py +++ b/examples/elm-pb/Python/grate.py @@ -8,12 +8,11 @@ from boututils.moment_xyzt import moment_xyzt +path = "./data/" -path='./data/' +p = collect("P", path=path) +rmsp_f = moment_xyzt(p[:, 34:35, 32:33, :], "RMS").rms -p=collect('P',path=path) -rmsp_f=moment_xyzt(p[:,34:35,32:33,:], 'RMS').rms - -print(np.gradient(np.log(rmsp_f[:,0,0]))[-1]) +print(np.gradient(np.log(rmsp_f[:, 0, 0]))[-1]) diff --git a/examples/elm-pb/Python/grate2.py b/examples/elm-pb/Python/grate2.py index f8172bcf08..af0768803a 100644 --- a/examples/elm-pb/Python/grate2.py +++ b/examples/elm-pb/Python/grate2.py @@ -2,6 +2,7 @@ from __future__ import division from builtins import range from past.utils import old_div + ### # computes average growth rate for all points at the final timestep # computes average growth rate for points in the mead plane at the final timestep @@ -10,40 +11,44 @@ from boutdata.collect import collect from boututils.moment_xyzt import moment_xyzt -path='./data/' +path = "./data/" + +p = collect("P", path=path) -p=collect('P',path=path) +nmpy = old_div(p.shape[2], 2) # define mead plane -nmpy=old_div(p.shape[2],2) # define mead plane +ik = 50 # disregard the first ik timesteps -ik = 50 # disregard the first ik timesteps def gr(p): - rmsp_f=moment_xyzt(p, 'RMS').rms + rmsp_f = moment_xyzt(p, "RMS").rms - ni=np.shape(rmsp_f)[1] - nj=np.shape(rmsp_f)[2] + ni = np.shape(rmsp_f)[1] + nj = np.shape(rmsp_f)[2] - growth=np.zeros((ni,nj)) + growth = np.zeros((ni, nj)) - for i in range(ni): - for j in range(nj): - growth[i,j]=np.gradient(np.log(rmsp_f[ik::,i,j]))[-1] + for i in range(ni): + for j in range(nj): + growth[i, j] = np.gradient(np.log(rmsp_f[ik::, i, j]))[-1] - return growth + return growth -growth=gr(p) +growth = gr(p) -d=np.ma.masked_array(growth,np.isnan(growth)) +d = np.ma.masked_array(growth, np.isnan(growth)) # masked arrays # http://stackoverflow.com/questions/5480694/numpy-calculate-averages-with-nans-removed -print('Total mean value = ', np.mean(np.ma.masked_array(d,np.isinf(d)))) -mm=np.ma.masked_array(growth[:,nmpy],np.isnan(growth[:,nmpy])) -if np.isinf(np.mean(mm)) : - print('There is an Inf value in the mead plane') - print('Mean value of floating numbers in mead plane is = ', np.mean(np.ma.masked_array(mm,np.isinf(mm)))) +print("Total mean value = ", np.mean(np.ma.masked_array(d, np.isinf(d)))) +mm = np.ma.masked_array(growth[:, nmpy], np.isnan(growth[:, nmpy])) +if np.isinf(np.mean(mm)): + print("There is an Inf value in the mead plane") + print( + "Mean value of floating numbers in mead plane is = ", + np.mean(np.ma.masked_array(mm, np.isinf(mm))), + ) else: - print('Mean value in mead plane= ', np.mean(mm)) + print("Mean value in mead plane= ", np.mean(mm)) diff --git a/examples/elm-pb/Python/plotcollapse.py b/examples/elm-pb/Python/plotcollapse.py index ee64ca381f..f68e7b06aa 100755 --- a/examples/elm-pb/Python/plotcollapse.py +++ b/examples/elm-pb/Python/plotcollapse.py @@ -10,49 +10,52 @@ import os from pathlib import Path -#Dynamic matplotlib settings +# Dynamic matplotlib settings from matplotlib import rcParams -rcParams['font.size'] = 20. -rcParams['legend.fontsize'] = 'small' -rcParams['lines.linewidth'] = 2 -if not os.path.exists('image'): - os.makedirs('image') +rcParams["font.size"] = 20.0 +rcParams["legend.fontsize"] = "small" +rcParams["lines.linewidth"] = 2 + +if not os.path.exists("image"): + os.makedirs("image") filename = Path(__file__).with_name("cbm18_dens8.grid_nx68ny64.nc") with DataFile(str(filename)) as f: g = {v: f.read(v) for v in f.keys()} -psi = old_div((g['psixy'][:, 32] - g['psi_axis']), (g['psi_bndry'] - g['psi_axis'])) +psi = old_div((g["psixy"][:, 32] - g["psi_axis"]), (g["psi_bndry"] - g["psi_axis"])) -path = './data' +path = "./data" plt.figure() -p0=collect('P0', path=path) +p0 = collect("P0", path=path) -p=collect('P', path=path) -res = moment_xyzt(p,'RMS','DC') +p = collect("P", path=path) +res = moment_xyzt(p, "RMS", "DC") rmsp = res.rms dcp = res.dc nt = dcp.shape[0] -plt.plot(psi, p0[:, 32], 'k--', label='t=0') -plt.plot(psi, p0[:, 32] + dcp[nt//4, :, 32], 'r-', label='t='+np.str(nt//4)) -plt.plot(psi, p0[:, 32] + dcp[nt//2, :, 32], 'g-', label='t='+np.str(nt//2)) -plt.plot(psi, p0[:, 32] + dcp[3*nt//4, :, 32], 'b-', label='t='+np.str(3*nt//4)) -plt.plot(psi, p0[:, 32] + dcp[-1, :, 32], 'c-', label='t='+np.str(nt)) +plt.plot(psi, p0[:, 32], "k--", label="t=0") +plt.plot(psi, p0[:, 32] + dcp[nt // 4, :, 32], "r-", label="t=" + np.str(nt // 4)) +plt.plot(psi, p0[:, 32] + dcp[nt // 2, :, 32], "g-", label="t=" + np.str(nt // 2)) +plt.plot( + psi, p0[:, 32] + dcp[3 * nt // 4, :, 32], "b-", label="t=" + np.str(3 * nt // 4) +) +plt.plot(psi, p0[:, 32] + dcp[-1, :, 32], "c-", label="t=" + np.str(nt)) plt.legend() -#plt.xlim(0.6, 1.0) -plt.xlabel(r'Normalized poloidal flux ($\psi$)') -plt.ylabel(r'$\langle p\rangle_\xi$') -plt.title(r'Pressure') +# plt.xlim(0.6, 1.0) +plt.xlabel(r"Normalized poloidal flux ($\psi$)") +plt.ylabel(r"$\langle p\rangle_\xi$") +plt.title(r"Pressure") xmin, xmax = plt.xlim() ymin, ymax = plt.ylim() -#plt.savefig('image/plotcollapse.png', bbox_inches='tight') -#plt.savefig('image/plotcollapse.eps', bbox_inches='tight') +# plt.savefig('image/plotcollapse.png', bbox_inches='tight') +# plt.savefig('image/plotcollapse.eps', bbox_inches='tight') plt.tight_layout() diff --git a/examples/elm-pb/Python/plotmode.py b/examples/elm-pb/Python/plotmode.py index d89fdaf940..9325ee8764 100644 --- a/examples/elm-pb/Python/plotmode.py +++ b/examples/elm-pb/Python/plotmode.py @@ -4,60 +4,57 @@ from builtins import range from past.utils import old_div -from numpy import *; -#from scipy.io import readsav; -import matplotlib.pyplot as plt; +from numpy import * + +# from scipy.io import readsav; +import matplotlib.pyplot as plt # Dynamic matplotlib settings -from matplotlib import rcParams; -rcParams['font.size'] = 20; -rcParams['legend.fontsize'] = 'small'; -rcParams['legend.labelspacing'] = 0.1; -rcParams['lines.linewidth'] = 2; -rcParams['savefig.bbox'] = 'tight'; +from matplotlib import rcParams +rcParams["font.size"] = 20 +rcParams["legend.fontsize"] = "small" +rcParams["legend.labelspacing"] = 0.1 +rcParams["lines.linewidth"] = 2 +rcParams["savefig.bbox"] = "tight" # Create image directory if not exists -import os; -if not os.path.exists('image'): - os.makedirs('image'); - -#fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; -fphi = load('fp.npy') - -plt.figure(); -for i in range(1, 9): - print("Growth rate for mode number", i) - print(gradient(log(abs(fphi[34, 32, i, :])))) - plt.semilogy(((abs(fphi[34, 32, i, :]))), label = 'n=' + str(i * 5)); +import os -plt.legend(loc=2); -plt.xlabel('Time'); -plt.savefig('image/plotmode.png'); -plt.savefig('image/plotmode.eps'); +if not os.path.exists("image"): + os.makedirs("image") +# fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; +fphi = load("fp.npy") -plt.show(block=False); -plt.figure(); +plt.figure() for i in range(1, 9): - plt.plot(abs(fphi[:, 32, i, -1]), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodeamp.png'); -plt.savefig('image/plotmodeamp.eps'); - -plt.show(block=False); - -plt.figure(); + print("Growth rate for mode number", i) + print(gradient(log(abs(fphi[34, 32, i, :])))) + plt.semilogy((abs(fphi[34, 32, i, :])), label="n=" + str(i * 5)) + +plt.legend(loc=2) +plt.xlabel("Time") +plt.savefig("image/plotmode.png") +plt.savefig("image/plotmode.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(old_div(abs(fphi[:, 32, i, -1]),abs(fphi[:, 32, i, -1]).max()), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodenorm.png'); -plt.savefig('image/plotmodenorm.eps'); - -plt.show(); - + plt.plot(abs(fphi[:, 32, i, -1]), label="n=" + str(i * 5)) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodeamp.png") +plt.savefig("image/plotmodeamp.eps") +plt.show(block=False) +plt.figure() +for i in range(1, 9): + plt.plot( + old_div(abs(fphi[:, 32, i, -1]), abs(fphi[:, 32, i, -1]).max()), + label="n=" + str(i * 5), + ) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodenorm.png") +plt.savefig("image/plotmodenorm.eps") +plt.show() diff --git a/examples/elm-pb/Python/plotmode2.py b/examples/elm-pb/Python/plotmode2.py index d0c63f32d9..c298a3a5ef 100644 --- a/examples/elm-pb/Python/plotmode2.py +++ b/examples/elm-pb/Python/plotmode2.py @@ -4,63 +4,61 @@ from builtins import range from past.utils import old_div -from numpy import *; -#from scipy.io import readsav; -import matplotlib.pyplot as plt; +from numpy import * + +# from scipy.io import readsav; +import matplotlib.pyplot as plt from boutdata.collect import collect # Dynamic matplotlib settings -from matplotlib import rcParams; -rcParams['font.size'] = 20; -rcParams['legend.fontsize'] = 'small'; -rcParams['legend.labelspacing'] = 0.1; -rcParams['lines.linewidth'] = 2; -rcParams['savefig.bbox'] = 'tight'; +from matplotlib import rcParams +rcParams["font.size"] = 20 +rcParams["legend.fontsize"] = "small" +rcParams["legend.labelspacing"] = 0.1 +rcParams["lines.linewidth"] = 2 +rcParams["savefig.bbox"] = "tight" # Create image directory if not exists -import os; -if not os.path.exists('image'): - os.makedirs('image'); +import os + +if not os.path.exists("image"): + os.makedirs("image") -path='./data/' -data=collect('P',path=path) +path = "./data/" +data = collect("P", path=path) -#fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; +# fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; fphi = fft.fft(data, axis=3) -plt.figure(); +plt.figure() for i in range(1, 9): - print("Growth rate for mode number", i) - print(gradient(log(abs(fphi[:,34, 32, i])))) - plt.semilogy(((abs(fphi[:,34, 32, i]))), label = 'n=' + str(i * 5)); - -plt.legend(loc=2); -plt.xlabel('Time'); -plt.savefig('image/plotmode.png'); -plt.savefig('image/plotmode.eps'); - - -plt.show(block=False); -plt.figure(); + print("Growth rate for mode number", i) + print(gradient(log(abs(fphi[:, 34, 32, i])))) + plt.semilogy((abs(fphi[:, 34, 32, i])), label="n=" + str(i * 5)) + +plt.legend(loc=2) +plt.xlabel("Time") +plt.savefig("image/plotmode.png") +plt.savefig("image/plotmode.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(abs(fphi[-1, :, 32, i]), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodeamp.png'); -plt.savefig('image/plotmodeamp.eps'); - -plt.show(block=False); - -plt.figure(); + plt.plot(abs(fphi[-1, :, 32, i]), label="n=" + str(i * 5)) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodeamp.png") +plt.savefig("image/plotmodeamp.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(old_div(abs(fphi[-1, :, 32, i]),abs(fphi[-1, :, 32, i]).max()), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodenorm.png'); -plt.savefig('image/plotmodenorm.eps'); - -plt.show(); + plt.plot( + old_div(abs(fphi[-1, :, 32, i]), abs(fphi[-1, :, 32, i]).max()), + label="n=" + str(i * 5), + ) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodenorm.png") +plt.savefig("image/plotmodenorm.eps") +plt.show() diff --git a/examples/elm-pb/Python/plotphase.py b/examples/elm-pb/Python/plotphase.py index 9225e498ae..10f4279cf4 100755 --- a/examples/elm-pb/Python/plotphase.py +++ b/examples/elm-pb/Python/plotphase.py @@ -4,34 +4,33 @@ from numpy import save, load, angle import matplotlib.pyplot as plt -fphi = load('fphi.npy') +fphi = load("fphi.npy") -fte = load('fte.npy') -phase_te = angle(old_div(fphi,fte)) -save('phase_te', phase_te) +fte = load("fte.npy") +phase_te = angle(old_div(fphi, fte)) +save("phase_te", phase_te) plt.figure() -plt.plot(mean(mean(phase_te[:,:,3,:],axis=1),axis=1)) -plt.title('Te') -plt.savefig('image/phase_te.png') -plt.savefig('image/phase_te.eps') +plt.plot(mean(mean(phase_te[:, :, 3, :], axis=1), axis=1)) +plt.title("Te") +plt.savefig("image/phase_te.png") +plt.savefig("image/phase_te.eps") -fti = load('fti.npy') -phase_ti = angle(old_div(fphi,fti)) -save('phase_ti', phase_ti) +fti = load("fti.npy") +phase_ti = angle(old_div(fphi, fti)) +save("phase_ti", phase_ti) plt.figure() -plt.plot(mean(mean(phase_ti[:,:,3,:],axis=1),axis=1)) -plt.title('ti') -plt.savefig('image/phase_ti.png') -plt.savefig('image/phase_ti.eps') +plt.plot(mean(mean(phase_ti[:, :, 3, :], axis=1), axis=1)) +plt.title("ti") +plt.savefig("image/phase_ti.png") +plt.savefig("image/phase_ti.eps") -fni = load('fni.npy') -phase_ni = angle(old_div(fphi,fni)) -save('phase_ni', phase_ni) +fni = load("fni.npy") +phase_ni = angle(old_div(fphi, fni)) +save("phase_ni", phase_ni) plt.figure() -plt.plot(mean(mean(phase_ni[:,:,3,:],axis=1),axis=1)) -plt.title('ni') -plt.savefig('image/phase_ni.png') -plt.savefig('image/phase_ni.eps') +plt.plot(mean(mean(phase_ni[:, :, 3, :], axis=1), axis=1)) +plt.title("ni") +plt.savefig("image/phase_ni.png") +plt.savefig("image/phase_ni.eps") plt.show() - diff --git a/examples/elm-pb/Python/polslice.py b/examples/elm-pb/Python/polslice.py index fe78495b5a..6a1179b2ae 100644 --- a/examples/elm-pb/Python/polslice.py +++ b/examples/elm-pb/Python/polslice.py @@ -11,31 +11,33 @@ # Specify parameters -path='./data/' +path = "./data/" -variable="P" +variable = "P" p = collect(variable, path=path) -period=15 +period = 15 -grid='../cbm18_dens8.grid_nx68ny64.nc' +grid = "../cbm18_dens8.grid_nx68ny64.nc" ######################################################## # Call plotpolslice once to get extended poloidal grid -r,z,fun=plotpolslice(p[0,:,:,:],grid,period=period,rz=1) +r, z, fun = plotpolslice(p[0, :, :, :], grid, period=period, rz=1) -nx=r.shape[0] # number of points in r -ny=r.shape[1] # number of points in z -nt=p.shape[0] # time intervals +nx = r.shape[0] # number of points in r +ny = r.shape[1] # number of points in z +nt = p.shape[0] # time intervals -fm=np.zeros((nt,nx,ny)) # array to store the time sequence of the poloidal cross section +fm = np.zeros( + (nt, nx, ny) +) # array to store the time sequence of the poloidal cross section -#Compute all time frames +# Compute all time frames for k in range(nt): - fm[k,:,:]=plotpolslice(p[k,:,:,:],grid,period=period,rz=0) + fm[k, :, :] = plotpolslice(p[k, :, :, :], grid, period=period, rz=0) -np.savez('pslice',fm=fm, z=z, r=r) +np.savez("pslice", fm=fm, z=z, r=r) diff --git a/examples/elm-pb/Python/post.py b/examples/elm-pb/Python/post.py index 9bb67347f0..cdaefa98cf 100644 --- a/examples/elm-pb/Python/post.py +++ b/examples/elm-pb/Python/post.py @@ -15,12 +15,12 @@ from mayavi import mlab -path0="./data0/" -path1="./data/" +path0 = "./data0/" +path1 = "./data/" -period=15 +period = 15 -gfile='./cbm18_dens8.grid_nx68ny64.nc' +gfile = "./cbm18_dens8.grid_nx68ny64.nc" with DataFile(gfile) as f: @@ -28,71 +28,115 @@ Dphi0 = collect("Dphi0", path=path0) -phi0 = collect("phi0", path=path1) # needs diamagnetic effects +phi0 = collect("phi0", path=path1) # needs diamagnetic effects # -psixy=g.get('psixy') -PSI_AXIS=g.get('psi_axis') -PSI_BNDRY=g.get('psi_bndry') +psixy = g.get("psixy") +PSI_AXIS = g.get("psi_axis") +PSI_BNDRY = g.get("psi_bndry") # -psix=old_div((psixy[:,32]-PSI_AXIS),(PSI_BNDRY-PSI_AXIS)) -Epsi=-deriv(phi0[:,32],psix) +psix = old_div((psixy[:, 32] - PSI_AXIS), (PSI_BNDRY - PSI_AXIS)) +Epsi = -deriv(phi0[:, 32], psix) # # -fig=figure() -plot(psix,-Dphi0[:,32], 'r', linewidth=5) -plot(psix,Epsi,'k',linewidth=5) -annotate('w/o flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -annotate('w/ flow', xy=(.7, .4), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='r', size=30) -xlabel('Radial $\psi$',fontsize=25) -ylabel('$\Omega(\psi)/\omega_A$',fontsize=25) -ylim([-.05,0]) -xlim([0.4,1.2]) +fig = figure() +plot(psix, -Dphi0[:, 32], "r", linewidth=5) +plot(psix, Epsi, "k", linewidth=5) +annotate( + "w/o flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +annotate( + "w/ flow", + xy=(0.7, 0.4), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="r", + size=30, +) +xlabel("Radial $\psi$", fontsize=25) +ylabel("$\Omega(\psi)/\omega_A$", fontsize=25) +ylim([-0.05, 0]) +xlim([0.4, 1.2]) fig.set_tight_layout(True) show(block=False) p_f0 = collect("P", path=path0) p_f = collect("P", path=path1) # -rmsp_f0=moment_xyzt(p_f0, 'RMS').rms -rmsp_f=moment_xyzt(p_f, 'RMS').rms +rmsp_f0 = moment_xyzt(p_f0, "RMS").rms +rmsp_f = moment_xyzt(p_f, "RMS").rms # -fig=figure(figsize=(10, 8)) -plot(np.gradient(np.log(rmsp_f0[:,34,32])), color='k',linewidth=3) -plot(np.gradient(np.log(rmsp_f[:,34,32])),color='red',linewidth=3) - -ylabel('$\gamma / \omega_A$',fontsize=25) -xlabel('Time$(\\tau_A)$',fontsize=25) -annotate('w/o flow', xy=(.5, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -annotate('w/ flow', xy=(.5, .4), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='r', size=30) -ylim([0,0.5]) -xlim([0,100]) +fig = figure(figsize=(10, 8)) +plot(np.gradient(np.log(rmsp_f0[:, 34, 32])), color="k", linewidth=3) +plot(np.gradient(np.log(rmsp_f[:, 34, 32])), color="red", linewidth=3) + +ylabel("$\gamma / \omega_A$", fontsize=25) +xlabel("Time$(\\tau_A)$", fontsize=25) +annotate( + "w/o flow", + xy=(0.5, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +annotate( + "w/ flow", + xy=(0.5, 0.4), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="r", + size=30, +) +ylim([0, 0.5]) +xlim([0, 100]) fig.set_tight_layout(True) show(block=False) - -plotpolslice(p_f0[50,:,:,:],gfile,period=period, fig=1) -mlab.text(.01,.99,"w/o flow") - -plotpolslice(p_f[50,:,:,:],gfile,period=period, fig=1) -mlab.text(.01,.99,"w/ flow") - -fig=figure() -mode_structure(p_f0[50,:,:,:], g, period=period) -plot([40,40],[0,.014],'k--',linewidth=5) -annotate('w/o flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -ylim([0,0.014]) -xlim([0,80]) +plotpolslice(p_f0[50, :, :, :], gfile, period=period, fig=1) +mlab.text(0.01, 0.99, "w/o flow") + +plotpolslice(p_f[50, :, :, :], gfile, period=period, fig=1) +mlab.text(0.01, 0.99, "w/ flow") + +fig = figure() +mode_structure(p_f0[50, :, :, :], g, period=period) +plot([40, 40], [0, 0.014], "k--", linewidth=5) +annotate( + "w/o flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +ylim([0, 0.014]) +xlim([0, 80]) fig.set_tight_layout(True) show(block=False) figure() -mode_structure(p_f[50,:,:,:], g, period=period) -plot([40,40],[0,.014],'k--',linewidth=5) -annotate('w/ flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='k', size=30) -ylim([0,0.0001]) -xlim([0,80]) +mode_structure(p_f[50, :, :, :], g, period=period) +plot([40, 40], [0, 0.014], "k--", linewidth=5) +annotate( + "w/ flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="k", + size=30, +) +ylim([0, 0.0001]) +xlim([0, 80]) show(block=False) show() diff --git a/examples/elm-pb/Python/read_elmsize.py b/examples/elm-pb/Python/read_elmsize.py index fcd3d24e53..340f57ce7b 100644 --- a/examples/elm-pb/Python/read_elmsize.py +++ b/examples/elm-pb/Python/read_elmsize.py @@ -4,12 +4,12 @@ from pylab import save, figure, plot, title, xlabel, ylabel, show, tight_layout from elm_size import elm_size -path='./data' +path = "./data" -t_array=collect('t_array', path=path) -save('t_array.dat', t_array) -p0=collect('P0', path=path) -save('p0.dat', p0) +t_array = collect("t_array", path=path) +save("t_array.dat", t_array) +p0 = collect("P0", path=path) +save("p0.dat", p0) # n0=collect('n0', path=path) @@ -22,27 +22,27 @@ with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: gfile = {v: f.read(v) for v in f.keys()} -p=collect('P', path=path) -save('p.dat', p) -res=moment_xyzt(p,'RMS','DC') -rmsp=res.rms -dcp=res.dc -save('rmsp.dat', rmsp) -save('dcp.dat', dcp) -elmsp=elm_size(dcp,p0,gfile,yind=32,Bbar=gfile['bmag']) -save('elmsp.dat', elmsp) +p = collect("P", path=path) +save("p.dat", p) +res = moment_xyzt(p, "RMS", "DC") +rmsp = res.rms +dcp = res.dc +save("rmsp.dat", rmsp) +save("dcp.dat", dcp) +elmsp = elm_size(dcp, p0, gfile, yind=32, Bbar=gfile["bmag"]) +save("elmsp.dat", elmsp) figure(0) -plot(t_array,elmsp.s2, 'k-') -xlabel('t/Ta') -ylabel('Elm size') -title('Elm size, P') +plot(t_array, elmsp.s2, "k-") +xlabel("t/Ta") +ylabel("Elm size") +title("Elm size, P") tight_layout() show() -phi=collect('phi', path=path ) -save('phi.dat', phi) -res=moment_xyzt( phi, 'DC', 'RMS') -save('dcphi.dat',res.dc) -save('rmsphi.dat', res.rms) +phi = collect("phi", path=path) +save("phi.dat", phi) +res = moment_xyzt(phi, "DC", "RMS") +save("dcphi.dat", res.dc) +save("rmsphi.dat", res.rms) diff --git a/examples/elm-pb/Python/showpolslice.py b/examples/elm-pb/Python/showpolslice.py index d292575e35..072c53dcd6 100644 --- a/examples/elm-pb/Python/showpolslice.py +++ b/examples/elm-pb/Python/showpolslice.py @@ -6,10 +6,12 @@ import numpy as np from tvtk.tools import visual + try: from enthought.mayavi import mlab except ImportError: - try: from mayavi import mlab + try: + from mayavi import mlab except ImportError: print("No mlab available") @@ -17,40 +19,42 @@ ########################### # Read polslice array -npzfile=np.load('pslice.npz') -r=npzfile['r'] -z=npzfile['z'] -fm=npzfile['fm'] +npzfile = np.load("pslice.npz") +r = npzfile["r"] +z = npzfile["z"] +fm = npzfile["fm"] ######################################################## # Set up the window -f = mlab.figure(size=(800,600)) +f = mlab.figure(size=(800, 600)) # Tell visual to use this as the viewer. visual.set_viewer(f) ######################################################## # Do the appropriate graph -#s = mlab.contour_surf(r,z,fun, contours=30, line_width=.5, transparent=True) -#s=mlab.surf(r,z,fun, colormap='Spectral') -s = mlab.mesh(r,z,fm[0,:,:], scalars=fm[0,:,:], colormap='PuOr')#, wrap_scale='true')#, representation='wireframe') -s.enable_contours=True -s.contour.filled_contours=True +# s = mlab.contour_surf(r,z,fun, contours=30, line_width=.5, transparent=True) +# s=mlab.surf(r,z,fun, colormap='Spectral') +s = mlab.mesh( + r, z, fm[0, :, :], scalars=fm[0, :, :], colormap="PuOr" +) # , wrap_scale='true')#, representation='wireframe') +s.enable_contours = True +s.contour.filled_contours = True # Define perspective and optional attributes. You can also implement from the window afterwards -mlab.view(0,0) -#mlab.view(-94.159958841373324, +mlab.view(0, 0) +# mlab.view(-94.159958841373324, # 53.777002382688906, # 8.2311808018087582) mlab.draw(f) mlab.colorbar(orientation="vertical") -#mlab.axes() -#mlab.outline() +# mlab.axes() +# mlab.outline() ######################################################## # mlab animation -anim(s,fm, save=True) +anim(s, fm, save=True) diff --git a/examples/elm-pb/Python/sprofiles.py b/examples/elm-pb/Python/sprofiles.py index 9d8eea48de..244599f8af 100644 --- a/examples/elm-pb/Python/sprofiles.py +++ b/examples/elm-pb/Python/sprofiles.py @@ -16,45 +16,46 @@ with DataFile(gfile) as f: g = {v: f.read(v) for v in f.keys()} -var=collect("P", path=path) +var = collect("P", path=path) -sol=surface_average(var, g) -#sol=np.mean(var,axis=3) +sol = surface_average(var, g) +# sol=np.mean(var,axis=3) -p0av=collect("P0", path=path) +p0av = collect("P0", path=path) -q=np.zeros(sol.shape) +q = np.zeros(sol.shape) for i in range(sol.shape[1]): - q[:,i]=sol[:,i]+p0av[:,0] + q[:, i] = sol[:, i] + p0av[:, 0] -psixy=g.get('psixy') -psi0=g.get('psi_axis') -psix=g.get('psi_bndry') +psixy = g.get("psixy") +psi0 = g.get("psi_axis") +psix = g.get("psi_bndry") -xarr = psixy[:,0] -xarr = old_div((xarr - psi0), (-psi0 + psix)) #for this grid +xarr = psixy[:, 0] +xarr = old_div((xarr - psi0), (-psi0 + psix)) # for this grid -fig=figure() +fig = figure() -nt=q.shape[1] +nt = q.shape[1] -plot(xarr, p0av,'k',label='t=0') -plot(xarr,q[:,nt/4],'r',label='t='+np.str(nt/4)) -plot(xarr,q[:,nt/2],'b',label='t='+np.str(nt/2)) -plot(xarr,q[:,3*nt/4],'g',label='t='+np.str(3*nt/4)) -plot(xarr, q[:,-1],'k',label='t='+np.str(nt)) +plot(xarr, p0av, "k", label="t=0") +plot(xarr, q[:, nt / 4], "r", label="t=" + np.str(nt / 4)) +plot(xarr, q[:, nt / 2], "b", label="t=" + np.str(nt / 2)) +plot(xarr, q[:, 3 * nt / 4], "g", label="t=" + np.str(3 * nt / 4)) +plot(xarr, q[:, -1], "k", label="t=" + np.str(nt)) from collections import OrderedDict + handles, labels = gca().get_legend_handles_labels() by_label = OrderedDict(list(zip(labels, handles))) legend(list(by_label.values()), list(by_label.keys())) -xlabel(r"$\psi$",fontsize=25) -ylabel(r"$2 \mu_0 / B^2$",fontsize=25) +xlabel(r"$\psi$", fontsize=25) +ylabel(r"$2 \mu_0 / B^2$", fontsize=25) fig.set_tight_layout(True) diff --git a/examples/elm-pb/runexample.py b/examples/elm-pb/runexample.py index f7ebc01028..b49902d29c 100755 --- a/examples/elm-pb/runexample.py +++ b/examples/elm-pb/runexample.py @@ -28,18 +28,22 @@ # Calculate RMS in toroidal direction prms = np.sqrt(np.mean(p**2, axis=3)) -growth = np.gradient(np.log(prms[:,42,32])) +growth = np.gradient(np.log(prms[:, 42, 32])) # Final growth-rate gamma = growth[-2] import matplotlib.pyplot as plt -plt.plot(tarr, prms[:,42,32], label='Outboard midplane') -plt.plot( [tarr[0], tarr[-1]], - [prms[-1,42,32]*np.exp(gamma*(tarr[0] - tarr[-1])), prms[-1,42,32]], '--', label=r'$\gamma =$'+str(gamma)) +plt.plot(tarr, prms[:, 42, 32], label="Outboard midplane") +plt.plot( + [tarr[0], tarr[-1]], + [prms[-1, 42, 32] * np.exp(gamma * (tarr[0] - tarr[-1])), prms[-1, 42, 32]], + "--", + label=r"$\gamma =$" + str(gamma), +) -plt.yscale('log') +plt.yscale("log") plt.grid() plt.xlabel(r"Time [$1/\tau_A$]") @@ -57,19 +61,21 @@ # Take a poloidal slice at fixed toroidal angle from boutdata.pol_slice import pol_slice -p2d = pol_slice(p[-1,:,:,:], 'cbm18_dens8.grid_nx68ny64.nc', n=15, zangle=0.0) + +p2d = pol_slice(p[-1, :, :, :], "cbm18_dens8.grid_nx68ny64.nc", n=15, zangle=0.0) # Read grid file to get coordinates from boututils.datafile import DataFile -g = DataFile('cbm18_dens8.grid_nx68ny64.nc') -Rxy = g.read("Rxy") # Major radius [m] -Zxy = g.read("Zxy") # Height [m] +g = DataFile("cbm18_dens8.grid_nx68ny64.nc") + +Rxy = g.read("Rxy") # Major radius [m] +Zxy = g.read("Zxy") # Height [m] plt.contourf(Rxy, Zxy, p2d, 30) -plt.axis('equal') # Maintain aspect ratio +plt.axis("equal") # Maintain aspect ratio -plt.colorbar() # Plot a bar down the side with a color scale +plt.colorbar() # Plot a bar down the side with a color scale plt.savefig("poloidal_slice.pdf") diff --git a/examples/fci-wave/compare-density.py b/examples/fci-wave/compare-density.py index c039c250b6..16e620a08f 100644 --- a/examples/fci-wave/compare-density.py +++ b/examples/fci-wave/compare-density.py @@ -1,4 +1,3 @@ - import matplotlib.pyplot as plt from boutdata import collect import numpy as np @@ -9,60 +8,61 @@ # Note: Data from fci-wave-logn examples commented out. data_noboundary = [ - ("div", "Model 1 (density, point interpolation)") - ,("div-integrate", "Model 2 (density, area integration)") - ,("logn", "Model 3 (log density, area integration)") - #,("../fci-wave-logn/div-integrate", "Model 5 (velocity, log density, area integration)") + ("div", "Model 1 (density, point interpolation)"), + ("div-integrate", "Model 2 (density, area integration)"), + ("logn", "Model 3 (log density, area integration)"), + # ,("../fci-wave-logn/div-integrate", "Model 5 (velocity, log density, area integration)") ] data_boundary = [ - ("boundary", "Model 2 (density, momentum)") - ,("boundary-logn", "Model 3 (log density, momentum)") - #,("../fci-wave-logn/boundary", "Model 5 (log density, velocity)") - ] + ("boundary", "Model 2 (density, momentum)"), + ("boundary-logn", "Model 3 (log density, momentum)"), + # ,("../fci-wave-logn/boundary", "Model 5 (log density, velocity)") +] # Change this to select no boundary or boundary cases data = data_noboundary if run: from boututils.run_wrapper import shell_safe, launch_safe + shell_safe("make > make.log") - for path,label in data: - launch_safe("./fci-wave -d "+path, nproc=nproc, pipe=False) + for path, label in data: + launch_safe("./fci-wave -d " + path, nproc=nproc, pipe=False) -# Collect the results into a dictionary +# Collect the results into a dictionary sum_n_B = {} -for path,label in data: +for path, label in data: n = collect("n", path=path) Bxyz = collect("Bxyz", path=path) time = collect("t_array", path=path) - + nt, nx, ny, nz = n.shape - + n_B = np.ndarray(nt) for t in range(nt): - n_B[t] = np.sum(n[t,:,:,:] / Bxyz) + n_B[t] = np.sum(n[t, :, :, :] / Bxyz) sum_n_B[path] = (time, n_B) # Plot the density at the final time - + plt.figure() - plt.contourf(n[-1,:,0,:].T, 100) + plt.contourf(n[-1, :, 0, :].T, 100) plt.colorbar() plt.xlabel("Major radius") plt.ylabel("Height") - plt.title("Density n, "+label) - plt.savefig(path+".pdf") + plt.title("Density n, " + label) + plt.savefig(path + ".pdf") plt.show() # Make a plot comparing total sum density / B - + plt.figure() -for path,label in data: +for path, label in data: time, n_B = sum_n_B[path] plt.plot(time, n_B, label=label) plt.legend() @@ -71,4 +71,3 @@ plt.savefig("compare-density.pdf") plt.show() - diff --git a/examples/finite-volume/diffusion/mms.py b/examples/finite-volume/diffusion/mms.py index 2c609ca82e..31b7714727 100644 --- a/examples/finite-volume/diffusion/mms.py +++ b/examples/finite-volume/diffusion/mms.py @@ -5,26 +5,26 @@ from math import pi # Length of the y domain -Ly = 10. +Ly = 10.0 # metric tensor metric = Metric() # Identity # Define solution in terms of input x,y,z -f = 1 + 0.1*sin(2*y - t) -k = 1 + 0.1*sin(y) +f = 1 + 0.1 * sin(2 * y - t) +k = 1 + 0.1 * sin(y) # Turn solution into real x and z coordinates -replace = [ (y, metric.y*2*pi/Ly) ] +replace = [(y, metric.y * 2 * pi / Ly)] f = f.subs(replace) -k = k.subs(replace) +k = k.subs(replace) ############################## # Calculate time derivatives -dfdt = Div_par( k * Grad_par(f) ) +dfdt = Div_par(k * Grad_par(f)) ############################# # Calculate sources @@ -32,7 +32,7 @@ Sf = diff(f, t) - dfdt # Substitute back to get input y coordinates -replace = [ (metric.y, y*Ly/(2*pi) ) ] +replace = [(metric.y, y * Ly / (2 * pi))] k = k.subs(replace) f = f.subs(replace) diff --git a/examples/finite-volume/fluid/mms.py b/examples/finite-volume/fluid/mms.py index 8ed8fba517..a31782e2c7 100644 --- a/examples/finite-volume/fluid/mms.py +++ b/examples/finite-volume/fluid/mms.py @@ -5,19 +5,19 @@ from math import pi # Length of the y domain -Ly = 10. +Ly = 10.0 # metric tensor metric = Metric() # Identity # Define solution in terms of input x,y,z -n = 1 + 0.1*sin(2*y - t) -p = 1 + 0.1*cos(3*y + t) -nv = 0.1*sin(y + 2*t) +n = 1 + 0.1 * sin(2 * y - t) +p = 1 + 0.1 * cos(3 * y + t) +nv = 0.1 * sin(y + 2 * t) # Turn solution into real x and z coordinates -replace = [ (y, metric.y*2*pi/Ly) ] +replace = [(y, metric.y * 2 * pi / Ly)] n = n.subs(replace) p = p.subs(replace) @@ -27,16 +27,16 @@ # Calculate time derivatives v = nv / n -gamma = 5./3 +gamma = 5.0 / 3 # Density equation -dndt = - Div_par(nv) +dndt = -Div_par(nv) # Pressure equation -dpdt = - Div_par(p*v) - (gamma-1.0)*p*Div_par(v) +dpdt = -Div_par(p * v) - (gamma - 1.0) * p * Div_par(v) # Momentum equation -dnvdt = - Div_par(nv*v) - Grad_par(p) +dnvdt = -Div_par(nv * v) - Grad_par(p) ############################# # Calculate sources @@ -46,7 +46,7 @@ Snv = diff(nv, t) - dnvdt # Substitute back to get input y coordinates -replace = [ (metric.y, y*Ly/(2*pi) ) ] +replace = [(metric.y, y * Ly / (2 * pi))] n = n.subs(replace) p = p.subs(replace) diff --git a/examples/laplace-petsc3d/plotcheck.py b/examples/laplace-petsc3d/plotcheck.py index 707e5db1ee..7f2758dd81 100755 --- a/examples/laplace-petsc3d/plotcheck.py +++ b/examples/laplace-petsc3d/plotcheck.py @@ -10,27 +10,27 @@ xg = 2 -f = collect('f', path=datadir)[xg:-xg, :, :] -rhs = collect('rhs', path=datadir)[xg:-xg, :, :] -rhs_check = collect('rhs_check', path=datadir)[xg:-xg, :, :] -error = collect('error', path=datadir)[xg:-xg, :, :] +f = collect("f", path=datadir)[xg:-xg, :, :] +rhs = collect("rhs", path=datadir)[xg:-xg, :, :] +rhs_check = collect("rhs_check", path=datadir)[xg:-xg, :, :] +error = collect("error", path=datadir)[xg:-xg, :, :] pyplot.subplot(221) pyplot.pcolormesh(f[:, yind, :]) pyplot.colorbar() -pyplot.title('f') +pyplot.title("f") pyplot.subplot(222) pyplot.pcolormesh(rhs[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs') +pyplot.title("rhs") pyplot.subplot(223) pyplot.pcolormesh(rhs_check[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs_check') +pyplot.title("rhs_check") pyplot.subplot(224) pyplot.pcolormesh(error[:, yind, :]) pyplot.colorbar() -pyplot.title('error') +pyplot.title("error") pyplot.show() diff --git a/examples/orszag-tang/generate.py b/examples/orszag-tang/generate.py index 3ba6dbbea9..acce7497c3 100644 --- a/examples/orszag-tang/generate.py +++ b/examples/orszag-tang/generate.py @@ -2,14 +2,16 @@ from __future__ import division from builtins import range from past.utils import old_div + # the Scientific Python netCDF 3 interface # http://dirac.cnrs-orleans.fr/ScientificPython/ -#from Scientific.IO.NetCDF import NetCDFFile as Dataset +# from Scientific.IO.NetCDF import NetCDFFile as Dataset # the 'classic' version of the netCDF4 python interface # http://code.google.com/p/netcdf4-python/ import numpy as np from netCDF4 import Dataset -from numpy import dtype # array module from http://numpy.scipy.org +from numpy import dtype # array module from http://numpy.scipy.org + """ This example writes some surface pressure and temperatures The companion program sfc_pres_temp_rd.py shows how to read the netCDF @@ -30,44 +32,45 @@ # # the output array to write will be nx x ny -ny = 100; nx = ny + 4 +ny = 100 +nx = ny + 4 # dy of grid dy = old_div(1.0, np.float(ny)) dx = dy # create grid -dxarr=np.zeros((nx,ny),dtype='float32')+dx -dyarr=np.zeros((nx,ny),dtype='float32')+dy +dxarr = np.zeros((nx, ny), dtype="float32") + dx +dyarr = np.zeros((nx, ny), dtype="float32") + dy -xarr=np.arange(0.,np.float(nx),1.,dtype='float32')*dx -yarr=np.arange(0.,np.float(ny),1.,dtype='float32')*dy +xarr = np.arange(0.0, np.float(nx), 1.0, dtype="float32") * dx +yarr = np.arange(0.0, np.float(ny), 1.0, dtype="float32") * dy # compute initial variables -rho=np.zeros((nx,ny),dtype='float32')+old_div(25.,(36.*np.pi)) -p=np.zeros((nx,ny),dtype='float32')+old_div(5.,(12.*np.pi)) +rho = np.zeros((nx, ny), dtype="float32") + old_div(25.0, (36.0 * np.pi)) +p = np.zeros((nx, ny), dtype="float32") + old_div(5.0, (12.0 * np.pi)) -rho=1. -p=old_div(rho,3.) +rho = 1.0 +p = old_div(rho, 3.0) -v_x=np.zeros((nx,ny),dtype='float32') -Bx=np.zeros((nx,ny),dtype='float32') +v_x = np.zeros((nx, ny), dtype="float32") +Bx = np.zeros((nx, ny), dtype="float32") for y in range(ny): - v_x[:,y]=-np.sin(2.*np.pi*yarr[y]) - Bx[:,y]=-np.sin(2.*np.pi*yarr[y]) - -#Bx=Bx/np.sqrt(4.*np.pi) + v_x[:, y] = -np.sin(2.0 * np.pi * yarr[y]) + Bx[:, y] = -np.sin(2.0 * np.pi * yarr[y]) +# Bx=Bx/np.sqrt(4.*np.pi) -v_y=np.zeros((nx,ny),dtype='float32') -By=np.zeros((nx,ny),dtype='float32') + +v_y = np.zeros((nx, ny), dtype="float32") +By = np.zeros((nx, ny), dtype="float32") for x in range(nx): - v_y[x,:]=np.sin(2.*np.pi*xarr[x]) - By[x,:]=np.sin(4.*np.pi*xarr[x]) - -#By=By/np.sqrt(4.*np.pi) + v_y[x, :] = np.sin(2.0 * np.pi * xarr[x]) + By[x, :] = np.sin(4.0 * np.pi * xarr[x]) + +# By=By/np.sqrt(4.*np.pi) # Domain inside core (periodic) @@ -76,55 +79,62 @@ ixseps2 = nx # open a new netCDF file for writing. -ncfile = Dataset('otv.grd.128.nc','w', format='NETCDF3_CLASSIC') +ncfile = Dataset("otv.grd.128.nc", "w", format="NETCDF3_CLASSIC") # output data. # create the nx and ny dimensions. -ncfile.createDimension('x',nx) -ncfile.createDimension('y',ny) -ncfile.createDimension('single',1) +ncfile.createDimension("x", nx) +ncfile.createDimension("y", ny) +ncfile.createDimension("single", 1) # create and write nx,ny variables -nxx=ncfile.createVariable('nx','i4',('single')) -nyy=ncfile.createVariable('ny','i4',('single')) +nxx = ncfile.createVariable("nx", "i4", ("single")) +nyy = ncfile.createVariable("ny", "i4", ("single")) -nxx[:]=nx -nyy[:]=ny +nxx[:] = nx +nyy[:] = ny # Define the coordinate variables. They will hold the coordinate # information, that is, xarr,yarr -dx = ncfile.createVariable('dx',dtype('float32').char,('x','y')) -dy = ncfile.createVariable('dy',dtype('float32').char,('x','y',)) +dx = ncfile.createVariable("dx", dtype("float32").char, ("x", "y")) +dy = ncfile.createVariable( + "dy", + dtype("float32").char, + ( + "x", + "y", + ), +) # write data to coordinate vars. -dx[:,:] = dxarr -dy[:,:] = dyarr +dx[:, :] = dxarr +dy[:, :] = dyarr # create and write ixseps* dimensions. -ix1=ncfile.createVariable('ixseps1','i4',('single')) -ix2=ncfile.createVariable('ixseps2','i4',('single')) +ix1 = ncfile.createVariable("ixseps1", "i4", ("single")) +ix2 = ncfile.createVariable("ixseps2", "i4", ("single")) -ix1[:]=ixseps1 -ix2[:]=ixseps2 +ix1[:] = ixseps1 +ix2[:] = ixseps2 -# create the corresponding variables -rho0 = ncfile.createVariable('rho0',dtype('float32').char,('x','y')) -p0 = ncfile.createVariable('p0',dtype('float32').char,('x','y')) -v0_x = ncfile.createVariable('v0_x',dtype('float32').char,('x','y')) -v0_y = ncfile.createVariable('v0_y',dtype('float32').char,('x','y')) -B0x = ncfile.createVariable('B0x',dtype('float32').char,('x','y')) -B0y = ncfile.createVariable('B0y',dtype('float32').char,('x','y')) +# create the corresponding variables +rho0 = ncfile.createVariable("rho0", dtype("float32").char, ("x", "y")) +p0 = ncfile.createVariable("p0", dtype("float32").char, ("x", "y")) +v0_x = ncfile.createVariable("v0_x", dtype("float32").char, ("x", "y")) +v0_y = ncfile.createVariable("v0_y", dtype("float32").char, ("x", "y")) +B0x = ncfile.createVariable("B0x", dtype("float32").char, ("x", "y")) +B0y = ncfile.createVariable("B0y", dtype("float32").char, ("x", "y")) # write data to variables. -rho0[:,:]=rho -p0[:,:]=p -v0_x[:,:]=v_x -v0_y[:,:]=v_y -B0x[:,:]=Bx -B0y[:,:]=By +rho0[:, :] = rho +p0[:, :] = p +v0_x[:, :] = v_x +v0_y[:, :] = v_y +B0x[:, :] = Bx +B0y[:, :] = By ncfile.close() -print('*** SUCCESS writing file otv.grd.py.nc!') +print("*** SUCCESS writing file otv.grd.py.nc!") diff --git a/examples/performance/bracket/scaling_parser.py b/examples/performance/bracket/scaling_parser.py index d7a23842d4..15f0ea8780 100644 --- a/examples/performance/bracket/scaling_parser.py +++ b/examples/performance/bracket/scaling_parser.py @@ -2,8 +2,7 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): @@ -13,7 +12,7 @@ def read_file(filename): for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} diff --git a/examples/performance/ddx/new_scaling_parser.py b/examples/performance/ddx/new_scaling_parser.py index d2a5fee191..5c0c92ff5e 100644 --- a/examples/performance/ddx/new_scaling_parser.py +++ b/examples/performance/ddx/new_scaling_parser.py @@ -2,19 +2,19 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): continue from collections import OrderedDict - case_lines = OrderedDict() #{} + + case_lines = OrderedDict() # {} for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} @@ -25,12 +25,13 @@ def read_file(filename): for title, col in zip(titles, line[:-1]): cases_weak[title].append(float(col)) - axis = cases_weak['Local grid'] + axis = cases_weak["Local grid"] data = [cases_weak[x] for x in case_lines] labels = [case_lines[x] for x in case_lines] - return {'axis':axis, 'data':data, 'labels':labels} + return {"axis": axis, "data": data, "labels": labels} + -def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): +def getScan(baseName="timing_{n}.txt", nthreads=(1, 2, 4, 8, 16, 32)): from numpy import zeros dataS = [] @@ -38,17 +39,16 @@ def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): f = baseName.format(n=n) dataS.append(read_file(f)) - nnt = len(dataS) - nlines = len(dataS[0]['data']) - nval = len(dataS[0]['data'][0]) - rawDat = zeros([nnt,nval,nlines]) + nlines = len(dataS[0]["data"]) + nval = len(dataS[0]["data"][0]) + rawDat = zeros([nnt, nval, nlines]) for i, dat in enumerate(dataS): - print(len(dat['data'])) - - rawDat[i,:,:] = dat['data'] + print(len(dat["data"])) + + rawDat[i, :, :] = dat["data"] - axes = [nthreads, dataS[0]['axis']] + axes = [nthreads, dataS[0]["axis"]] - return axes, rawDat, dataS[0]['labels'] + return axes, rawDat, dataS[0]["labels"] diff --git a/examples/performance/ddy/new_scaling_parser.py b/examples/performance/ddy/new_scaling_parser.py index d2a5fee191..5c0c92ff5e 100644 --- a/examples/performance/ddy/new_scaling_parser.py +++ b/examples/performance/ddy/new_scaling_parser.py @@ -2,19 +2,19 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): continue from collections import OrderedDict - case_lines = OrderedDict() #{} + + case_lines = OrderedDict() # {} for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} @@ -25,12 +25,13 @@ def read_file(filename): for title, col in zip(titles, line[:-1]): cases_weak[title].append(float(col)) - axis = cases_weak['Local grid'] + axis = cases_weak["Local grid"] data = [cases_weak[x] for x in case_lines] labels = [case_lines[x] for x in case_lines] - return {'axis':axis, 'data':data, 'labels':labels} + return {"axis": axis, "data": data, "labels": labels} + -def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): +def getScan(baseName="timing_{n}.txt", nthreads=(1, 2, 4, 8, 16, 32)): from numpy import zeros dataS = [] @@ -38,17 +39,16 @@ def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): f = baseName.format(n=n) dataS.append(read_file(f)) - nnt = len(dataS) - nlines = len(dataS[0]['data']) - nval = len(dataS[0]['data'][0]) - rawDat = zeros([nnt,nval,nlines]) + nlines = len(dataS[0]["data"]) + nval = len(dataS[0]["data"][0]) + rawDat = zeros([nnt, nval, nlines]) for i, dat in enumerate(dataS): - print(len(dat['data'])) - - rawDat[i,:,:] = dat['data'] + print(len(dat["data"])) + + rawDat[i, :, :] = dat["data"] - axes = [nthreads, dataS[0]['axis']] + axes = [nthreads, dataS[0]["axis"]] - return axes, rawDat, dataS[0]['labels'] + return axes, rawDat, dataS[0]["labels"] diff --git a/examples/performance/ddz/new_scaling_parser.py b/examples/performance/ddz/new_scaling_parser.py index d2a5fee191..5c0c92ff5e 100644 --- a/examples/performance/ddz/new_scaling_parser.py +++ b/examples/performance/ddz/new_scaling_parser.py @@ -2,19 +2,19 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): continue from collections import OrderedDict - case_lines = OrderedDict() #{} + + case_lines = OrderedDict() # {} for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} @@ -25,12 +25,13 @@ def read_file(filename): for title, col in zip(titles, line[:-1]): cases_weak[title].append(float(col)) - axis = cases_weak['Local grid'] + axis = cases_weak["Local grid"] data = [cases_weak[x] for x in case_lines] labels = [case_lines[x] for x in case_lines] - return {'axis':axis, 'data':data, 'labels':labels} + return {"axis": axis, "data": data, "labels": labels} + -def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): +def getScan(baseName="timing_{n}.txt", nthreads=(1, 2, 4, 8, 16, 32)): from numpy import zeros dataS = [] @@ -38,17 +39,16 @@ def getScan(baseName = "timing_{n}.txt", nthreads = (1,2,4,8,16,32)): f = baseName.format(n=n) dataS.append(read_file(f)) - nnt = len(dataS) - nlines = len(dataS[0]['data']) - nval = len(dataS[0]['data'][0]) - rawDat = zeros([nnt,nval,nlines]) + nlines = len(dataS[0]["data"]) + nval = len(dataS[0]["data"][0]) + rawDat = zeros([nnt, nval, nlines]) for i, dat in enumerate(dataS): - print(len(dat['data'])) - - rawDat[i,:,:] = dat['data'] + print(len(dat["data"])) + + rawDat[i, :, :] = dat["data"] - axes = [nthreads, dataS[0]['axis']] + axes = [nthreads, dataS[0]["axis"]] - return axes, rawDat, dataS[0]['labels'] + return axes, rawDat, dataS[0]["labels"] diff --git a/examples/performance/iterator/scaling_parser.py b/examples/performance/iterator/scaling_parser.py index d7a23842d4..15f0ea8780 100644 --- a/examples/performance/iterator/scaling_parser.py +++ b/examples/performance/iterator/scaling_parser.py @@ -2,8 +2,7 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): @@ -13,7 +12,7 @@ def read_file(filename): for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} diff --git a/examples/staggered_grid/generate.py b/examples/staggered_grid/generate.py index da84e9c2e6..a5a0120612 100755 --- a/examples/staggered_grid/generate.py +++ b/examples/staggered_grid/generate.py @@ -4,11 +4,11 @@ # Generate an input mesh # -from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries +from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries -nx = 5 # Minimum is 5: 2 boundary, one evolved +nx = 5 # Minimum is 5: 2 boundary, one evolved ny = 32 # Minimum 5. Should be divisible by number of processors (so powers of 2 nice) -dy = 1. # distance between points in y, in m/g22/lengthunit +dy = 1.0 # distance between points in y, in m/g22/lengthunit ixseps1 = -1 ixseps2 = -1 diff --git a/examples/subsampling/show.py b/examples/subsampling/show.py index 34c6ee3084..b79c5e2964 100755 --- a/examples/subsampling/show.py +++ b/examples/subsampling/show.py @@ -11,14 +11,14 @@ for pack in monitors: filename, data_name = pack - t = DataFile(path+'/'+filename+'.dmp.0.nc').read('t_array') - data = DataFile(path+'/'+filename+'.dmp.0.nc').read(data_name).flatten() + t = DataFile(path + "/" + filename + ".dmp.0.nc").read("t_array") + data = DataFile(path + "/" + filename + ".dmp.0.nc").read(data_name).flatten() plt.plot(t, data, label="{} {}".format(filename, data_name)) -time = DataFile(path+'/BOUT.dmp.0.nc').read('t_array') -data = DataFile(path+'/BOUT.dmp.0.nc').read("T")[:, 2, 2, 0] +time = DataFile(path + "/BOUT.dmp.0.nc").read("t_array") +data = DataFile(path + "/BOUT.dmp.0.nc").read("T")[:, 2, 2, 0] -plt.plot(time, data, marker='+', label="BOUT++ T") +plt.plot(time, data, marker="+", label="BOUT++ T") plt.xlabel("Time") plt.legend() diff --git a/examples/wave-slab/generate.py b/examples/wave-slab/generate.py index 0a2e8f3049..12698d1e24 100755 --- a/examples/wave-slab/generate.py +++ b/examples/wave-slab/generate.py @@ -51,7 +51,7 @@ for x in range(nx): Bpxy[x, :] = Bpx[x] -Bxy = sqrt(Bpxy ** 2 + Bt ** 2) +Bxy = sqrt(Bpxy**2 + Bt**2) # Calculate change in poloidal flux dr = Lx / nx # Constant mesh spacing in radius diff --git a/manual/sphinx/figs/figure_creators/LaplacianMatrices.ipynb b/manual/sphinx/figs/figure_creators/LaplacianMatrices.ipynb index c3c39a3c12..4e940b998f 100644 --- a/manual/sphinx/figs/figure_creators/LaplacianMatrices.ipynb +++ b/manual/sphinx/figs/figure_creators/LaplacianMatrices.ipynb @@ -40,10 +40,10 @@ "outputs": [], "source": [ "# Note, these can be max 9 due to the current index convention\n", - "nx = 3 # Not including ghost points\n", + "nx = 3 # Not including ghost points\n", "nz = 3\n", "\n", - "startXIndex = 10 # The x indices are the slowest growing indices\n", + "startXIndex = 10 # The x indices are the slowest growing indices\n", "startZIndex = 1 # The z indices are the fastest growing indices" ] }, @@ -85,13 +85,13 @@ "for z in range(nz):\n", " f.append([])\n", " xStart = startZIndex\n", - " xEnd = startXIndex*(nx+1) # +1 due to ghost point\n", + " xEnd = startXIndex * (nx + 1) # +1 due to ghost point\n", " # +startXIndex in the range as the range does not include endpoint\n", - " for xInd in range(xStart, xEnd+startXIndex, 10):\n", - " ind = str(xInd+z)\n", - " if (xInd+z) < startXIndex:\n", - " ind = '0'+str(xInd+z)\n", - " f[z].append(symbols('f_' + ind))\n", + " for xInd in range(xStart, xEnd + startXIndex, 10):\n", + " ind = str(xInd + z)\n", + " if (xInd + z) < startXIndex:\n", + " ind = \"0\" + str(xInd + z)\n", + " f[z].append(symbols(\"f_\" + ind))\n", "\n", "mesh = Matrix(f[::-1])\n", "display(mesh)" @@ -195,21 +195,21 @@ } ], "source": [ - "xVec=[]\n", - "bVec=[]\n", + "xVec = []\n", + "bVec = []\n", "# Do the inner loop, so start ranges at 1\n", "# (nx+1) to include outer ghost point, +1 in the range as the range does not include endpoint\n", - "for x in range(1, (nx+1)+1):\n", - " for z in range(1,nz+1):\n", - " xVec.append(symbols('x_'+str(x)+'_'+str(z)))\n", - " bVec.append(symbols('b_'+str(x)+'_'+str(z)))\n", + "for x in range(1, (nx + 1) + 1):\n", + " for z in range(1, nz + 1):\n", + " xVec.append(symbols(\"x_\" + str(x) + \"_\" + str(z)))\n", + " bVec.append(symbols(\"b_\" + str(x) + \"_\" + str(z)))\n", "\n", "# Do the inner ghost points\n", "# Must count backwards since we are inserting in the front\n", - "for ind in range(nz,0,-1):\n", - " xVec.insert(0, symbols('x_0_'+str(ind)))\n", - " bVec.insert(0, symbols('b_0_'+str(ind)))\n", - " \n", + "for ind in range(nz, 0, -1):\n", + " xVec.insert(0, symbols(\"x_0_\" + str(ind)))\n", + " bVec.insert(0, symbols(\"b_0_\" + str(ind)))\n", + "\n", "display(Matrix(xVec))\n", "display(Matrix(bVec))" ] @@ -274,7 +274,7 @@ "globInd = []\n", "for rows in range(len(xVec)):\n", " cols = []\n", - " for col in range(rows*len(xVec), (rows+1)*len(xVec)):\n", + " for col in range(rows * len(xVec), (rows + 1) * len(xVec)):\n", " cols.append(col)\n", " globInd.append(cols)\n", "\n", @@ -305,10 +305,14 @@ "source": [ "c = []\n", "for x in range(nx):\n", - " indexStart = (startXIndex+1)+(startXIndex*x) # Multiply by 10 due to index system\n", - " indexEnd = (startXIndex+nz+1)+(startXIndex*x) # Multiply by 10 due to index system\n", + " indexStart = (startXIndex + 1) + (\n", + " startXIndex * x\n", + " ) # Multiply by 10 due to index system\n", + " indexEnd = (startXIndex + nz + 1) + (\n", + " startXIndex * x\n", + " ) # Multiply by 10 due to index system\n", " for ind in range(indexStart, indexEnd):\n", - " c.append(symbols('c_'+str(ind)))" + " c.append(symbols(\"c_\" + str(ind)))" ] }, { @@ -328,11 +332,11 @@ "source": [ "# The inner ghost\n", "innerGhostStart = startZIndex\n", - "innerGhostEnd = nz\n", + "innerGhostEnd = nz\n", "ig = []\n", "# +1 in the range as last point is not included\n", - "for z in range(innerGhostStart, innerGhostEnd+1):\n", - " ig.append(symbols('ig_0_'+str(z)))" + "for z in range(innerGhostStart, innerGhostEnd + 1):\n", + " ig.append(symbols(\"ig_0_\" + str(z)))" ] }, { @@ -345,12 +349,12 @@ "source": [ "# The outer ghost\n", "# nx+1 as we want to go past the last inner x grid point\n", - "outerGhostStart = startXIndex*(nx+1) + startZIndex\n", - "outerGhostEnd = startXIndex*(nx+1) + nz\n", + "outerGhostStart = startXIndex * (nx + 1) + startZIndex\n", + "outerGhostEnd = startXIndex * (nx + 1) + nz\n", "og = []\n", "# +1 in the range as last point is not included\n", - "for z in range(outerGhostStart, outerGhostEnd+1):\n", - " og.append(symbols('og_'+str(z)))" + "for z in range(outerGhostStart, outerGhostEnd + 1):\n", + " og.append(symbols(\"og_\" + str(z)))" ] }, { @@ -396,21 +400,27 @@ "for x in range(nx):\n", " # The indices referring to the matrix index\n", " # The last -1 is there as the matrix indices count from 0\n", - " startRow = (nz+1)+(x*nz)-1 # Starting at row+1 after inner ghost point sub-matrix\n", - " endRow = (nz+1)+(x*nz)+(nz-1)-1 # Ending row-1 before the last z-index (last z will be wrapped around)\n", + " startRow = (\n", + " (nz + 1) + (x * nz) - 1\n", + " ) # Starting at row+1 after inner ghost point sub-matrix\n", + " endRow = (\n", + " (nz + 1) + (x * nz) + (nz - 1) - 1\n", + " ) # Ending row-1 before the last z-index (last z will be wrapped around)\n", " # +1 in range as last point is not included\n", - " rows = range(startRow, endRow+1)\n", - " cols = range(startRow+1, endRow+1) # Column is shifted +1 from the diagonal\n", - " \n", + " rows = range(startRow, endRow + 1)\n", + " cols = range(startRow + 1, endRow + 1) # Column is shifted +1 from the diagonal\n", + "\n", " # The indices referring to the spatial point in the grid\n", " # The last \"+1\" is fue to the fact that the column is shifted +1 from the diagonal\n", - " startInd = (startXIndex+startZIndex) + (startXIndex*x) + 1\n", - " endInd = (startXIndex+startZIndex) + (nz-1) + (startXIndex*x) + 1 # Wrap around last point\n", + " startInd = (startXIndex + startZIndex) + (startXIndex * x) + 1\n", + " endInd = (\n", + " (startXIndex + startZIndex) + (nz - 1) + (startXIndex * x) + 1\n", + " ) # Wrap around last point\n", " # +1 in range as last point is not included\n", - " inds = range(startInd, endInd+1)\n", - " \n", + " inds = range(startInd, endInd + 1)\n", + "\n", " for rInd, cInd, ind in zip(rows, cols, inds):\n", - " InvM[rInd, cInd] = symbols('zp_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"zp_\" + str(ind))" ] }, { @@ -423,15 +433,17 @@ "source": [ "# The wrap around\n", "# The index referring to the spatial point in the grid\n", - "startInd = startXIndex+startZIndex\n", + "startInd = startXIndex + startZIndex\n", "# The indices referring to the matrix index\n", - "# Last -1 as the matrix indices are counted from 0 \n", - "startRow = (nz+1) + (nz-1) - 1 # nz+1 below from the ghost sub matrix, nz-1 below after that\n", - "startCol = (nz+1)-1 # nz+1 left of the ghost sub matrix\n", + "# Last -1 as the matrix indices are counted from 0\n", + "startRow = (\n", + " (nz + 1) + (nz - 1) - 1\n", + ") # nz+1 below from the ghost sub matrix, nz-1 below after that\n", + "startCol = (nz + 1) - 1 # nz+1 left of the ghost sub matrix\n", "for wrap in range(nx):\n", - " row = startRow+wrap*nz\n", - " col = startCol+wrap*nz\n", - " InvM[row, col] = symbols('zp_'+str(startInd+startXIndex*wrap))" + " row = startRow + wrap * nz\n", + " col = startCol + wrap * nz\n", + " InvM[row, col] = symbols(\"zp_\" + str(startInd + startXIndex * wrap))" ] }, { @@ -452,20 +464,26 @@ "for x in range(nx):\n", " # The indices referring to the matrix index\n", " # The last -1 is there as the matrix indices count from 0\n", - " startRow = (nz+1)+(x*nz)-1 # Starting at row+1 after inner ghost point sub-matrix\n", - " endRow = (nz+1)+(x*nz)+(nz-1)-1 # Ending row-1 before the last z-index (last z will be wrapped around)\n", + " startRow = (\n", + " (nz + 1) + (x * nz) - 1\n", + " ) # Starting at row+1 after inner ghost point sub-matrix\n", + " endRow = (\n", + " (nz + 1) + (x * nz) + (nz - 1) - 1\n", + " ) # Ending row-1 before the last z-index (last z will be wrapped around)\n", " # +1 in range as last point is not included\n", - " rows = range(startRow+1, endRow+1) # Row is shifted +1 from the diagonal\n", - " cols = range(startRow, endRow+1)\n", - " \n", + " rows = range(startRow + 1, endRow + 1) # Row is shifted +1 from the diagonal\n", + " cols = range(startRow, endRow + 1)\n", + "\n", " # The indices referring to the spatial point in the grid\n", - " startInd = (startXIndex+startZIndex) + (startXIndex*x)\n", - " endInd = (startXIndex+startZIndex) + (nz-1) + (startXIndex*x) # Wrap around last point\n", + " startInd = (startXIndex + startZIndex) + (startXIndex * x)\n", + " endInd = (\n", + " (startXIndex + startZIndex) + (nz - 1) + (startXIndex * x)\n", + " ) # Wrap around last point\n", " # +1 in range as last point is not included\n", - " inds = range(startInd, endInd+1)\n", - " \n", + " inds = range(startInd, endInd + 1)\n", + "\n", " for rInd, cInd, ind in zip(rows, cols, inds):\n", - " InvM[rInd, cInd] = symbols('zm_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"zm_\" + str(ind))" ] }, { @@ -478,15 +496,19 @@ "source": [ "# The wrap around\n", "# The index referring to the spatial point in the grid\n", - "startInd = startXIndex+startZIndex+(nz-1) # +(nz-1) as this will be the last z point for the current x\n", + "startInd = (\n", + " startXIndex + startZIndex + (nz - 1)\n", + ") # +(nz-1) as this will be the last z point for the current x\n", "# The indices referring to the matrix index\n", - "# Last -1 as the matrix indices are counted from 0 \n", - "startRow = (nz+1)-1 # nz+1 below the ghost sub matrix\n", - "startCol = (nz+1) + (nz-1) - 1 # nz+1 left from the ghost sub matrix, nz-1 left after that\n", + "# Last -1 as the matrix indices are counted from 0\n", + "startRow = (nz + 1) - 1 # nz+1 below the ghost sub matrix\n", + "startCol = (\n", + " (nz + 1) + (nz - 1) - 1\n", + ") # nz+1 left from the ghost sub matrix, nz-1 left after that\n", "for wrap in range(nx):\n", - " row = startRow+wrap*nz\n", - " col = startCol+wrap*nz\n", - " InvM[row, col] = symbols('zm_'+str(startInd+startXIndex*wrap))" + " row = startRow + wrap * nz\n", + " col = startCol + wrap * nz\n", + " InvM[row, col] = symbols(\"zm_\" + str(startInd + startXIndex * wrap))" ] }, { @@ -505,23 +527,29 @@ "outputs": [], "source": [ "# Indices referring to the spatial points in the grid\n", - "startInd = startXIndex*2 + startZIndex # *2 as we start at the second inner x-index\n", - "endInd = startInd + (startZIndex*nz) # *nz as this is the last z-index in the current x-index\n", + "startInd = startXIndex * 2 + startZIndex # *2 as we start at the second inner x-index\n", + "endInd = startInd + (\n", + " startZIndex * nz\n", + ") # *nz as this is the last z-index in the current x-index\n", "\n", "for x in range(nx):\n", " # The indices referring to the matrix index\n", " # The last -1 as the matrix indices counts from 0\n", - " startRow = (nz+1)+(x*nz)-1 # Starting at row+1 after inner ghost point sub-matrix\n", - " endRow = (nz+1)+(x*nz)+(nz)-1 # Ending at the row referring to the last z-index\n", + " startRow = (\n", + " (nz + 1) + (x * nz) - 1\n", + " ) # Starting at row+1 after inner ghost point sub-matrix\n", + " endRow = (\n", + " (nz + 1) + (x * nz) + (nz) - 1\n", + " ) # Ending at the row referring to the last z-index\n", " # Not +1 in range as we do not want to include last point\n", - " rows = range(startRow, endRow)\n", - " cols = range(startRow+nz, endRow+nz) # Start at first index after last z-index\n", - " \n", + " rows = range(startRow, endRow)\n", + " cols = range(startRow + nz, endRow + nz) # Start at first index after last z-index\n", + "\n", " # Indices referring to the spatial points in the grid\n", - " inds = range(startInd+startXIndex*x, endInd+startXIndex*x)\n", - " \n", + " inds = range(startInd + startXIndex * x, endInd + startXIndex * x)\n", + "\n", " for rInd, cInd, ind in zip(rows, cols, inds):\n", - " InvM[rInd, cInd] = symbols('xp_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"xp_\" + str(ind))" ] }, { @@ -534,22 +562,22 @@ "source": [ "# x+1 for inner ghost point\n", "# Indices referring to the spatial points in the grid\n", - "startInd = startXIndex + startZIndex # First inner point for first z\n", - "endInd = startInd + (startZIndex*nz) # First inner point for last z\n", + "startInd = startXIndex + startZIndex # First inner point for first z\n", + "endInd = startInd + (startZIndex * nz) # First inner point for last z\n", "\n", "# The indices referring to the matrix index\n", "# The last -1 as the matrix indices counts from 0\n", - "startRow = startZIndex-1 # Starting at first row\n", - "endRow = startZIndex+nz-1 # Ending at the row referring to the last z-index\n", + "startRow = startZIndex - 1 # Starting at first row\n", + "endRow = startZIndex + nz - 1 # Ending at the row referring to the last z-index\n", "# Not +1 in range as we do not want to include last point\n", - "rows = range(startRow, endRow)\n", - "cols = range(startRow+nz, endRow+nz) # Start at first index after last z-index\n", - " \n", + "rows = range(startRow, endRow)\n", + "cols = range(startRow + nz, endRow + nz) # Start at first index after last z-index\n", + "\n", "# Indices referring to the spatial points in the grid\n", - "inds = range(startInd, endInd)\n", - " \n", + "inds = range(startInd, endInd)\n", + "\n", "for rInd, cInd, ind in zip(rows, cols, inds):\n", - " InvM[rInd, cInd] = symbols('igxp_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"igxp_\" + str(ind))" ] }, { @@ -569,25 +597,25 @@ "source": [ "# Indices referring to the spatial points in the grid\n", "startInd = startZIndex\n", - "endInd = startInd + nz\n", + "endInd = startInd + nz\n", "\n", "for x in range(nx):\n", " # The indices referring to the matrix index\n", " # Note that x starts counting from zero, so we must add 1 to x in the rows\n", - " startRow = ((x+1)*nz) # Starting at row+1 after inner ghost point sub-matrix\n", - " endRow = ((x+1)*nz)+(nz) # Ending at the row referring to the last z-index\n", + " startRow = (x + 1) * nz # Starting at row+1 after inner ghost point sub-matrix\n", + " endRow = ((x + 1) * nz) + (nz) # Ending at the row referring to the last z-index\n", " # Not +1 in range as we do not want to include last point\n", - " rows = range(startRow, endRow)\n", - " cols = range(startRow-nz, endRow-nz) # Start at first index after last z-index\n", - " \n", + " rows = range(startRow, endRow)\n", + " cols = range(startRow - nz, endRow - nz) # Start at first index after last z-index\n", + "\n", " # Indices referring to the spatial points in the grid\n", - " inds = range(startInd+startXIndex*x, endInd+startXIndex*x)\n", - " \n", + " inds = range(startInd + startXIndex * x, endInd + startXIndex * x)\n", + "\n", " for rInd, cInd, ind in zip(rows, cols, inds):\n", " if (ind) < startXIndex:\n", - " ind = '0'+str(ind)\n", + " ind = \"0\" + str(ind)\n", "\n", - " InvM[rInd, cInd] = symbols('xm_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"xm_\" + str(ind))" ] }, { @@ -600,22 +628,24 @@ "source": [ "# x-1 for inner ghost point\n", "# Indices referring to the spatial points in the grid\n", - "startInd = startXIndex*nx + startZIndex # Last inner point for first z\n", - "endInd = startInd + (startZIndex*nz) # Last inner point for last z\n", + "startInd = startXIndex * nx + startZIndex # Last inner point for first z\n", + "endInd = startInd + (startZIndex * nz) # Last inner point for last z\n", "\n", "# The indices referring to the matrix index\n", "# The last -1 as the matrix indices counts from 0\n", - "startRow = len(xVec)-nz-1 # Starting at last inner point row\n", - "endRow = len(xVec)-1 # Ending at the last row\n", + "startRow = len(xVec) - nz - 1 # Starting at last inner point row\n", + "endRow = len(xVec) - 1 # Ending at the last row\n", "# +1 in range as last point is not included\n", - "rows = range(startRow+1, endRow+1)\n", - "cols = range(startRow-nz+1, endRow-nz+1) # Start at first index after last z-index\n", - " \n", + "rows = range(startRow + 1, endRow + 1)\n", + "cols = range(\n", + " startRow - nz + 1, endRow - nz + 1\n", + ") # Start at first index after last z-index\n", + "\n", "# Indices referring to the spatial points in the grid\n", - "inds = range(startInd, endInd)\n", - " \n", + "inds = range(startInd, endInd)\n", + "\n", "for rInd, cInd, ind in zip(rows, cols, inds):\n", - " InvM[rInd, cInd] = symbols('ogxm_'+str(ind))" + " InvM[rInd, cInd] = symbols(\"ogxm_\" + str(ind))" ] }, { diff --git a/manual/sphinx/figs/figure_creators/bout_runners_folder_structure.py b/manual/sphinx/figs/figure_creators/bout_runners_folder_structure.py index 8a95a13436..5a4a2a0843 100644 --- a/manual/sphinx/figs/figure_creators/bout_runners_folder_structure.py +++ b/manual/sphinx/figs/figure_creators/bout_runners_folder_structure.py @@ -10,10 +10,10 @@ mmag@fysik.dtu.dk """ -__authors__ = 'Michael Loeiten' -__email__ = 'mmag@fysik.dtu.dk' -__version__ = '1.0' -__date__ = '21.01.2016' +__authors__ = "Michael Loeiten" +__email__ = "mmag@fysik.dtu.dk" +__version__ = "1.0" +__date__ = "21.01.2016" import pygraphviz as pgv @@ -21,113 +21,118 @@ tree = pgv.AGraph() # Appendable lists -files = [] +files = [] dead_ends = [] # Default node attributes -tree.node_attr['shape']='box' -tree.node_attr['style']='bold' +tree.node_attr["shape"] = "box" +tree.node_attr["style"] = "bold" # Adding nodes and edges -l0 = 'project' -l1 = ['data', 'source\nfiles', 'driver.py'] +l0 = "project" +l1 = ["data", "source\nfiles", "driver.py"] # Append the files files.append(l1[1]) files.append(l1[2]) # Add the boxes to the mother node for box in l1: - tree.add_edge(l0,box) + tree.add_edge(l0, box) -l2 = ['solver1', 'solver2',\ - 'BOUT.inp', 'run_log.txt'] +l2 = ["solver1", "solver2", "BOUT.inp", "run_log.txt"] # Append the files files.append(l2[2]) files.append(l2[3]) # Add the boxes to the mother node for box in l2: - tree.add_edge('data', box) -tree.add_edge('solver2', 'solver2/...') + tree.add_edge("data", box) +tree.add_edge("solver2", "solver2/...") # Append the dead_end -de = l2[1] + '/...' +de = l2[1] + "/..." dead_ends.append(de) -l3 = ['method1', 'method2', 'solver1/...'] +l3 = ["method1", "method2", "solver1/..."] for box in l3: - tree.add_edge('solver1', box) -tree.add_edge('method2', 'method2/...') + tree.add_edge("solver1", box) +tree.add_edge("method2", "method2/...") # Append the dead_end de = l3[2] dead_ends.append(de) -de = l3[1] + '/...' +de = l3[1] + "/..." dead_ends.append(de) -l4 = ['nout\ntimestep1', 'nout\ntimestep2', 'method1/...'] +l4 = ["nout\ntimestep1", "nout\ntimestep2", "method1/..."] for box in l4: - tree.add_edge('method1', box) -tree.add_edge('nout\ntimestep2', 'nout\ntimestep2/...') + tree.add_edge("method1", box) +tree.add_edge("nout\ntimestep2", "nout\ntimestep2/...") # Append the dead_end de = l4[2] dead_ends.append(de) -de = l4[1] + '/...' +de = l4[1] + "/..." dead_ends.append(de) -l5 = ['mesh1', 'mesh2', 'nout\ntimestep1/...'] +l5 = ["mesh1", "mesh2", "nout\ntimestep1/..."] for box in l5: - tree.add_edge('nout\ntimestep1', box) -tree.add_edge('mesh2', 'mesh2/...') + tree.add_edge("nout\ntimestep1", box) +tree.add_edge("mesh2", "mesh2/...") # Append the dead_end de = l5[2] dead_ends.append(de) -de = l5[1] + '/...' +de = l5[1] + "/..." dead_ends.append(de) -l6 = ['additional1', 'additional2', 'mesh1/...'] +l6 = ["additional1", "additional2", "mesh1/..."] for box in l6: - tree.add_edge('mesh1', box) -tree.add_edge('additional2', 'additional2/...') + tree.add_edge("mesh1", box) +tree.add_edge("additional2", "additional2/...") # Append the dead_end de = l6[2] dead_ends.append(de) -de = l6[1] + '/...' +de = l6[1] + "/..." dead_ends.append(de) -l7 = ['grid_file1', 'grid_file2', 'additional1/...'] +l7 = ["grid_file1", "grid_file2", "additional1/..."] for box in l7: - tree.add_edge('additional1', box) -tree.add_edge('grid_file2', 'grid_file2/...') + tree.add_edge("additional1", box) +tree.add_edge("grid_file2", "grid_file2/...") # Append the dead_end de = l7[2] dead_ends.append(de) -de = l7[1] + '/...' +de = l7[1] + "/..." dead_ends.append(de) -l8 = ['BOUT.inp\n(copy)', 'BOUT.log', 'BOUT.dmp',\ - 'BOUT.restart', '(source_files\n(copy))', '(grid_file\n(copy))'] +l8 = [ + "BOUT.inp\n(copy)", + "BOUT.log", + "BOUT.dmp", + "BOUT.restart", + "(source_files\n(copy))", + "(grid_file\n(copy))", +] # Add l8 to the files list for cur_file in l8: files.append(cur_file) # Append them to the mother node for box in l8: - tree.add_edge('grid_file1', box) + tree.add_edge("grid_file1", box) # Change colors for the files for the_file in files: - member=tree.get_node(the_file) -# member.attr['fontcolor'] = 'limegreen' - member.attr['color'] = 'limegreen' + member = tree.get_node(the_file) + # member.attr['fontcolor'] = 'limegreen' + member.attr["color"] = "limegreen" # Change colors for the dead_ends for dead_end in dead_ends: - member=tree.get_node(dead_end) -# member.attr['fontcolor'] = 'darksalmon' - member.attr['color'] = 'darksalmon' + member = tree.get_node(dead_end) + # member.attr['fontcolor'] = 'darksalmon' + member.attr["color"] = "darksalmon" # Print the graph print(tree.string()) # Set layout -tree.layout('dot') +tree.layout("dot") # Write to file -tree.draw('folder_tree.svg') +tree.draw("folder_tree.svg") diff --git a/tests/MMS/advection/runtest b/tests/MMS/advection/runtest index 9a0a691287..5109c47815 100755 --- a/tests/MMS/advection/runtest +++ b/tests/MMS/advection/runtest @@ -50,7 +50,7 @@ def run_mms(options, exit=True): dx = 2.0 * pi / (nx) - args = f"{opts} mesh:nx={nx+4} mesh:dx={dx} MZ={nx}" + args = f"{opts} mesh:nx={nx + 4} mesh:dx={dx} MZ={nx}" print(" Running with " + args) From 03283f45a50a4f883ca0f1a95c906474b7f4e4d5 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:52:26 +0000 Subject: [PATCH 57/71] [bot] Add last format changes commit to ignore file --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 4990f2586e..a6948a0684 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,4 @@ # Clang-format whole repo d8f14fdddb5ca0fbb32d8e2bf5ac2960d6ac5ce6 ed2117e6d6826a98b6988e2f18c0c34e408563b6 +52301380586fdbf890f620c04f689b08d89a6c34 From 26651cc10565d47b381febf3b863f3ee79dca597 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 2 Feb 2026 12:15:45 +0100 Subject: [PATCH 58/71] Revert accidential typo --- src/mesh/coordinates.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index b8b0f9ea55..086fa2e23e 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1590,7 +1590,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, f_B.yup(i) = f.yup(i) / Bxy_floc.yup(i); f_B.ydown(i) = f.ydown(i) / Bxy_floc.ydown(i); } - return xy * Grad_par(f_B, outloc, method); + return Bxy * Grad_par(f_B, outloc, method); } ///////////////////////////////////////////////////////// From f319c61b58ecb145e1607846e10e6748713fd519 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:04:49 +0100 Subject: [PATCH 59/71] Fix comment --- include/bout/options_io.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index 509305aad0..3892ccbc1f 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -14,7 +14,7 @@ /// /// 2. Restart files: /// -/// auto restart = OptionsIOFactory::getInstance().createOutput(); +/// auto restart = OptionsIOFactory::getInstance().createRestart(); /// restart->write(data); /// /// where data is an Options tree. By default restart files are configured From 1519bf29232c90be0933153d7a6ae027f7887e29 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:11:06 +0100 Subject: [PATCH 60/71] Add simple method to write data in parallel --- include/bout/options_io.hxx | 28 ++++++++++++++++++++-------- src/sys/options/options_io.cxx | 9 +++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index 3892ccbc1f..f35aab6716 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -5,8 +5,8 @@ /// /// 1. Dump files, containing time history: /// -/// auto dump = OptionsIOFactory::getInstance().createOutput(); -/// dump->write(data); +/// auto dump = OptionsIOFactory::getInstance().createOutput(); +/// dump->write(data); /// /// where data is an Options tree. By default dump files are configured /// with the root `output` section, or an Option tree can be passed to @@ -14,20 +14,27 @@ /// /// 2. Restart files: /// -/// auto restart = OptionsIOFactory::getInstance().createRestart(); -/// restart->write(data); +/// auto restart = OptionsIOFactory::getInstance().createRestart(); +/// restart->write(data); /// /// where data is an Options tree. By default restart files are configured /// with the root `restart_files` section, or an Option tree can be passed to /// `createRestart`. /// /// 3. Ad-hoc single files -/// Note: The caller should consider how multiple processors interact with the file. +/// Note: The caller should consider how multiple processors interact with the file. /// -/// auto file = OptionsIOFactory::getInstance().createFile("some_file.nc"); -/// or -/// auto file = OptionsIO::create("some_file.nc"); +/// auto file = OptionsIOFactory::getInstance().createFile("some_file.nc"); +/// or +/// auto file = OptionsIO::create("some_file.nc"); /// +/// 4. Ad-hoc parallel files +/// This adds also metric information, such that the file can be read with +/// boutdata or xBOUT +/// +/// OptionIO::write("some_file", data, mesh); +/// +/// if mesh is omitted, no grid information is added. /// #pragma once @@ -77,6 +84,11 @@ public: /// This uses the default file type and default options. static std::unique_ptr create(const std::string& file); + /// Write some data to a file with a given name prefix + /// This will be done in parallel. If Mesh is given, also mesh data will be + /// added, which is needed for xBOUT or boutdata to read the files. + static void write(const std::string& prefix, Options data, Mesh* mesh = nullptr); + /// Create an OptionsIO for I/O to the given file. /// The file will be configured using the given `config` options: /// - "type" : string The file type e.g. "netcdf" or "adios" diff --git a/src/sys/options/options_io.cxx b/src/sys/options/options_io.cxx index 6717b6b07d..9ac5b69cc8 100644 --- a/src/sys/options/options_io.cxx +++ b/src/sys/options/options_io.cxx @@ -2,6 +2,7 @@ #include "bout/bout.hxx" #include "bout/globals.hxx" #include "bout/mesh.hxx" +#include "bout/version.hxx" #include "options_adios.hxx" #include "options_netcdf.hxx" @@ -55,4 +56,12 @@ void writeDefaultOutputFile(Options& data) { OptionsIOFactory::getInstance().createOutput()->write(data); } +void OptionsIO::write(const std::string& prefix, Options data, Mesh* mesh) { + Options file_options = {{"prefix", prefix}}; + data["BOUT_VERSION"].force(bout::version::as_double); + if (mesh != nullptr) { + mesh->outputVars(data); + } + OptionsIOFactory::getInstance().createOutput(&file_options)->write(data); +} } // namespace bout From b61f8158906fa877a806523a93de181465d82988 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:11:26 +0100 Subject: [PATCH 61/71] Use new interface to write data Allows to use other backends then netcdf --- src/solver/impls/euler/euler.cxx | 13 ++----------- src/solver/impls/pvode/pvode.cxx | 12 +----------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 6bdceab516..ed8621a874 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -164,19 +164,10 @@ void EulerSolver::take_step(BoutReal curtime, BoutReal dt, Array& star mesh = f.var->getMesh(); } - if (mesh != nullptr) { - mesh->outputVars(debug); - debug["BOUT_VERSION"].force(bout::version::as_double); - } - const std::string outnumber = dump_at_time < -3 ? fmt::format(".{}", debug_counter++) : ""; - const std::string outname = - fmt::format("{}/BOUT.debug{}.{}.nc", - Options::root()["datadir"].withDefault("data"), - outnumber, BoutComm::rank()); - - bout::OptionsIO::create(outname)->write(debug); + const std::string outname = fmt::format("BOUT.debug{}", outnumber); + bout::OptionsIO::write(outname, debug, mesh); MPI_Barrier(BoutComm::get()); for (auto& f : f3d) { f.F_var->disableTracking(); diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 4cc90af8fd..5fbabe5bd2 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -399,17 +399,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { for (auto& f : f3d) { saveParallel(debug, f.name, *f.var); } - - if (mesh != nullptr) { - mesh->outputVars(debug); - debug["BOUT_VERSION"].force(bout::version::as_double); - } - - const std::string outname = fmt::format( - "{}/BOUT.debug.{}.nc", - Options::root()["datadir"].withDefault("data"), BoutComm::rank()); - - bout::OptionsIO::create(outname)->write(debug); + bout::OptionsIO::write("BOUT.debug", debug, mesh); MPI_Barrier(BoutComm::get()); } return -1.0; From eab6b0356545c84114ffdd7b6d351f77671d17d9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:30:10 +0100 Subject: [PATCH 62/71] Add docs on using solver-dumping --- manual/sphinx/developer_docs/debugging.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/manual/sphinx/developer_docs/debugging.rst b/manual/sphinx/developer_docs/debugging.rst index f16d0b6a3b..63c4f4e389 100644 --- a/manual/sphinx/developer_docs/debugging.rst +++ b/manual/sphinx/developer_docs/debugging.rst @@ -158,3 +158,23 @@ If you need to capture runtime information in the message, you can use the ``fmt`` syntax also used by the loggers:: TRACE("Value of i={}, some arbitrary {}", i, "string"); + + +Time evolution +============== + +It can be convinient to know what happend when the simulation failed. +The pvode solver can dump the state of the simulation, at the time where the +solver failed. This information does include the single terms in the +derivative. This allows to identify which term is causing the issue. +In addition the residuum is dump. This not only tells which term, but also +where the solver is struggeling. +This can be enabled with:: + + solver:type=pvode solver:debug_on_failure=true + +It is also possible to dump at a specific time using the euler solver. +This can be handy to track down what is causing differences between two +different versions. It can be used with:: + + solver:type=euler solver:dump_at_time=0 input:error_on_unused_options=false From 508dcdae51d09b49f12b1303d834275b0229a03a Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:39:14 +0100 Subject: [PATCH 63/71] Improve docs --- manual/sphinx/developer_docs/debugging.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/manual/sphinx/developer_docs/debugging.rst b/manual/sphinx/developer_docs/debugging.rst index 63c4f4e389..b23d882a42 100644 --- a/manual/sphinx/developer_docs/debugging.rst +++ b/manual/sphinx/developer_docs/debugging.rst @@ -163,18 +163,18 @@ the ``fmt`` syntax also used by the loggers:: Time evolution ============== -It can be convinient to know what happend when the simulation failed. -The pvode solver can dump the state of the simulation, at the time where the -solver failed. This information does include the single terms in the -derivative. This allows to identify which term is causing the issue. -In addition the residuum is dump. This not only tells which term, but also -where the solver is struggeling. -This can be enabled with:: +It can be useful to know what happened when the simulation failed. The pvode +solver can dump the state of the simulation, at the time the solver +failed. This information includes the individual terms in the derivative. This +allows to identify which term is causing the issue. Additionally, the +residuum is dumped. This identifies not only which term is causing the issue, +but also where in the domain the solver is struggling. This can be enabled +with:: solver:type=pvode solver:debug_on_failure=true It is also possible to dump at a specific time using the euler solver. -This can be handy to track down what is causing differences between two +This can be useful for tracking down what is causing differences between two different versions. It can be used with:: solver:type=euler solver:dump_at_time=0 input:error_on_unused_options=false From c9732b7fa2802b07dd2c329b04df647fafb63ad4 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:48:31 +0100 Subject: [PATCH 64/71] Add more docs --- manual/sphinx/developer_docs/debugging.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/manual/sphinx/developer_docs/debugging.rst b/manual/sphinx/developer_docs/debugging.rst index b23d882a42..4f47cd63e3 100644 --- a/manual/sphinx/developer_docs/debugging.rst +++ b/manual/sphinx/developer_docs/debugging.rst @@ -171,10 +171,17 @@ residuum is dumped. This identifies not only which term is causing the issue, but also where in the domain the solver is struggling. This can be enabled with:: - solver:type=pvode solver:debug_on_failure=true + solver:type=pvode solver:debug_on_failure=true + +It can be also useful for understanding why the solver is slow. Forcing a +higher min_timestep, the solver will fail to evolve the system as it +encounters the situation, and provides information where it is happening. +This can be done with:: + + solver:type=pvode solver:debug_on_failure=true solver:min_timestep=1e2 It is also possible to dump at a specific time using the euler solver. This can be useful for tracking down what is causing differences between two different versions. It can be used with:: - solver:type=euler solver:dump_at_time=0 input:error_on_unused_options=false + solver:type=euler solver:dump_at_time=0 input:error_on_unused_options=false From 9b96dad5490af5515fad8464f830a22335a831be Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 14:50:05 +0100 Subject: [PATCH 65/71] simplify to_load creation Co-authored-by: Peter Hill --- src/solver/impls/pvode/pvode.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 5fbabe5bd2..d8e2ab2438 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -380,9 +380,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { std::vector evolve_bndrys{}; for (const auto& f : f3d) { mesh = f.var->getMesh(); - Field3D to_load{0., mesh}; - to_load.allocate(); - to_load.setLocation(f.location); + Field3D to_load{0., mesh}.setLocation(f.location); debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; list_of_fields.push_back(to_load); evolve_bndrys.push_back(f.evolve_bndry); From 94f9ea601d153f3f8020efa7fb38b4448aaf5e61 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 15:13:46 +0100 Subject: [PATCH 66/71] Fixup to_load --- src/solver/impls/pvode/pvode.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index d8e2ab2438..95adecaec1 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -380,7 +380,8 @@ BoutReal PvodeSolver::run(BoutReal tout) { std::vector evolve_bndrys{}; for (const auto& f : f3d) { mesh = f.var->getMesh(); - Field3D to_load{0., mesh}.setLocation(f.location); + Field3D to_load{0., mesh}; + to_load.setLocation(f.location); debug[fmt::format("{:s}{:s}", prefix, f.name)] = to_load; list_of_fields.push_back(to_load); evolve_bndrys.push_back(f.evolve_bndry); From 6ec39173f20de8a3aab59cf24f23e5793623fee6 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 3 Feb 2026 15:35:18 +0100 Subject: [PATCH 67/71] Take reference to avoid copy --- include/bout/options_io.hxx | 2 +- src/sys/options/options_io.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index f35aab6716..4fab70aea8 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -87,7 +87,7 @@ public: /// Write some data to a file with a given name prefix /// This will be done in parallel. If Mesh is given, also mesh data will be /// added, which is needed for xBOUT or boutdata to read the files. - static void write(const std::string& prefix, Options data, Mesh* mesh = nullptr); + static void write(const std::string& prefix, Options& data, Mesh* mesh = nullptr); /// Create an OptionsIO for I/O to the given file. /// The file will be configured using the given `config` options: diff --git a/src/sys/options/options_io.cxx b/src/sys/options/options_io.cxx index 9ac5b69cc8..256ec56b28 100644 --- a/src/sys/options/options_io.cxx +++ b/src/sys/options/options_io.cxx @@ -56,7 +56,7 @@ void writeDefaultOutputFile(Options& data) { OptionsIOFactory::getInstance().createOutput()->write(data); } -void OptionsIO::write(const std::string& prefix, Options data, Mesh* mesh) { +void OptionsIO::write(const std::string& prefix, Options& data, Mesh* mesh) { Options file_options = {{"prefix", prefix}}; data["BOUT_VERSION"].force(bout::version::as_double); if (mesh != nullptr) { From 6f19419c56a3fee47b9cb90855eaaac7fcc0b0fa Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 13 Feb 2026 14:05:18 +0100 Subject: [PATCH 68/71] Cleanup included headers --- include/bout/options_io.hxx | 1 + src/solver/impls/euler/euler.cxx | 2 +- src/solver/impls/pvode/pvode.cxx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index 4fab70aea8..81addc1521 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -45,6 +45,7 @@ #include "bout/build_defines.hxx" #include "bout/generic_factory.hxx" #include "bout/options.hxx" +#include "bout/mesh.hxx" #include #include diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index ed8621a874..19dc9d7015 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 95adecaec1..115ffb2056 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -37,9 +37,9 @@ #include #include #include +#include #include #include -#include #include #include // use CVSPGMR linear solver each internal step From b04a24232eeeeee29ff5e5951f2b9011f863c3d7 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 13 Feb 2026 14:05:32 +0100 Subject: [PATCH 69/71] Switch to [[maybe_unused]] --- src/solver/impls/pvode/pvode.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index 115ffb2056..aadb4a87c6 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -39,7 +39,6 @@ #include #include #include -#include #include #include // use CVSPGMR linear solver each internal step @@ -411,7 +410,7 @@ BoutReal PvodeSolver::run(BoutReal tout) { * RHS function **************************************************************************/ -void PvodeSolver::rhs(int UNUSED(N), BoutReal t, BoutReal* udata, BoutReal* dudata) { +void PvodeSolver::rhs([[maybe_unused]] int N, BoutReal t, BoutReal* udata, BoutReal* dudata) { TRACE("Running RHS: PvodeSolver::rhs({})", t); // Get current timestep @@ -427,7 +426,7 @@ void PvodeSolver::rhs(int UNUSED(N), BoutReal t, BoutReal* udata, BoutReal* duda save_derivs(dudata); } -void PvodeSolver::gloc(int UNUSED(N), BoutReal t, BoutReal* udata, BoutReal* dudata) { +void PvodeSolver::gloc([[maybe_unused]] int N, BoutReal t, BoutReal* udata, BoutReal* dudata) { TRACE("Running RHS: PvodeSolver::gloc({})", t); Timer timer("rhs"); @@ -468,8 +467,8 @@ void solver_gloc(integer N, BoutReal t, BoutReal* u, BoutReal* udot, void* f_dat } // Preconditioner communication function -void solver_cfn(integer UNUSED(N), BoutReal UNUSED(t), N_Vector UNUSED(u), - void* UNUSED(f_data)) { +void solver_cfn([[maybe_unused]] integer N, [[maybe_unused]] BoutReal t, [[maybe_unused]] N_Vector u, + [[maybe_unused]] void* f_data) { // doesn't do anything at the moment } From 83cf77923a4c72e44303354923021acf932b4fd2 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:07:08 +0000 Subject: [PATCH 70/71] [bot] Apply format changes --- include/bout/options_io.hxx | 2 +- src/solver/impls/euler/euler.cxx | 2 +- src/solver/impls/pvode/pvode.cxx | 12 +++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index 81addc1521..00dd0c4cf3 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -44,8 +44,8 @@ #include "bout/build_defines.hxx" #include "bout/generic_factory.hxx" -#include "bout/options.hxx" #include "bout/mesh.hxx" +#include "bout/options.hxx" #include #include diff --git a/src/solver/impls/euler/euler.cxx b/src/solver/impls/euler/euler.cxx index 19dc9d7015..9754a68826 100644 --- a/src/solver/impls/euler/euler.cxx +++ b/src/solver/impls/euler/euler.cxx @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/solver/impls/pvode/pvode.cxx b/src/solver/impls/pvode/pvode.cxx index aadb4a87c6..8ccd5f134a 100644 --- a/src/solver/impls/pvode/pvode.cxx +++ b/src/solver/impls/pvode/pvode.cxx @@ -36,8 +36,8 @@ #include #include #include -#include #include +#include #include #include @@ -410,7 +410,8 @@ BoutReal PvodeSolver::run(BoutReal tout) { * RHS function **************************************************************************/ -void PvodeSolver::rhs([[maybe_unused]] int N, BoutReal t, BoutReal* udata, BoutReal* dudata) { +void PvodeSolver::rhs([[maybe_unused]] int N, BoutReal t, BoutReal* udata, + BoutReal* dudata) { TRACE("Running RHS: PvodeSolver::rhs({})", t); // Get current timestep @@ -426,7 +427,8 @@ void PvodeSolver::rhs([[maybe_unused]] int N, BoutReal t, BoutReal* udata, BoutR save_derivs(dudata); } -void PvodeSolver::gloc([[maybe_unused]] int N, BoutReal t, BoutReal* udata, BoutReal* dudata) { +void PvodeSolver::gloc([[maybe_unused]] int N, BoutReal t, BoutReal* udata, + BoutReal* dudata) { TRACE("Running RHS: PvodeSolver::gloc({})", t); Timer timer("rhs"); @@ -467,8 +469,8 @@ void solver_gloc(integer N, BoutReal t, BoutReal* u, BoutReal* udot, void* f_dat } // Preconditioner communication function -void solver_cfn([[maybe_unused]] integer N, [[maybe_unused]] BoutReal t, [[maybe_unused]] N_Vector u, - [[maybe_unused]] void* f_data) { +void solver_cfn([[maybe_unused]] integer N, [[maybe_unused]] BoutReal t, + [[maybe_unused]] N_Vector u, [[maybe_unused]] void* f_data) { // doesn't do anything at the moment } From bc86a19972d60c640c60268e880de9883870dd2d Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:07:10 +0000 Subject: [PATCH 71/71] [bot] Add last format changes commit to ignore file --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 31b33eb76b..99f926614e 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -5,3 +5,4 @@ ed2117e6d6826a98b6988e2f18c0c34e408563b6 4b010b7634aee1045743be80c268d4644522cd29 52301380586fdbf890f620c04f689b08d89a6c34 a71cad2dd6ace5741a754e2ca7daacd4bb094e0e +83cf77923a4c72e44303354923021acf932b4fd2