-
Notifications
You must be signed in to change notification settings - Fork 106
Add cell volume and areas #3326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
3f521d0
3065f88
1c0e385
5c28542
078322d
7547d9e
01d776b
13fdb8a
db66e35
cca09ac
a0d4954
aae5b5d
63ab8b4
6b66188
4c0c495
fd12c54
1b83ae8
f9cf8d2
7ad4d05
6751afd
042cf65
cc172bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,16 +3,16 @@ | |
| * | ||
| * ChangeLog | ||
| * ========= | ||
| * | ||
| * | ||
| * 2014-11-10 Ben Dudson <bd512@york.ac.uk> | ||
| * * Created by separating metric from Mesh | ||
| * | ||
| * | ||
| * | ||
| ************************************************************************** | ||
| * Copyright 2014-2025 BOUT++ contributors | ||
| * | ||
| * Contact: Ben Dudson, dudson2@llnl.gov | ||
| * | ||
| * | ||
| * This file is part of BOUT++. | ||
| * | ||
| * BOUT++ is free software: you can redistribute it and/or modify | ||
|
|
@@ -38,6 +38,7 @@ | |
| #include <bout/field2d.hxx> | ||
| #include <bout/field3d.hxx> | ||
| #include <bout/paralleltransform.hxx> | ||
| #include <optional> | ||
|
|
||
| class Mesh; | ||
|
|
||
|
|
@@ -102,6 +103,112 @@ public: | |
| /// Covariant metric tensor | ||
| FieldMetric g_11, g_22, g_33, g_12, g_13, g_23; | ||
|
|
||
| /// get g_22 at the cell faces; | ||
| const FieldMetric& g_22_ylow() const; | ||
| const FieldMetric& g_22_yhigh() const; | ||
| FieldMetric& g_22_ylow(); | ||
| FieldMetric& g_22_yhigh(); | ||
| // Cell Areas | ||
| const FieldMetric& cell_area_xlow() const { | ||
| if (!_cell_area_xlow.has_value()) { | ||
| _compute_cell_area_x(); | ||
| } | ||
| return *_cell_area_xlow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_xlow;
^ |
||
| } | ||
| const FieldMetric& cell_area_xhigh() const { | ||
| if (!_cell_area_xhigh.has_value()) { | ||
| _compute_cell_area_x(); | ||
| } | ||
| return *_cell_area_xhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_xhigh;
^ |
||
| } | ||
| const FieldMetric& cell_area_ylow() const { | ||
| if (!_cell_area_ylow.has_value()) { | ||
| _compute_cell_area_y(); | ||
| } | ||
| return *_cell_area_ylow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_ylow;
^ |
||
| } | ||
| const FieldMetric& cell_area_yhigh() const { | ||
| if (!_cell_area_yhigh.has_value()) { | ||
| _compute_cell_area_y(); | ||
| } | ||
| return *_cell_area_yhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_yhigh;
^ |
||
| } | ||
| const FieldMetric& cell_area_zlow() const { | ||
| if (!_cell_area_zlow.has_value()) { | ||
| _compute_cell_area_z(); | ||
| } | ||
| return *_cell_area_zlow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_zlow;
^ |
||
| } | ||
| const FieldMetric& cell_area_zhigh() const { | ||
| if (!_cell_area_zhigh.has_value()) { | ||
| _compute_cell_area_z(); | ||
| } | ||
| return *_cell_area_zhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_zhigh;
^ |
||
| } | ||
| FieldMetric& cell_area_xlow() { | ||
| if (!_cell_area_xlow.has_value()) { | ||
| _compute_cell_area_x(); | ||
| } | ||
| return *_cell_area_xlow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_xlow;
^ |
||
| } | ||
| FieldMetric& cell_area_xhigh() { | ||
| if (!_cell_area_xhigh.has_value()) { | ||
| _compute_cell_area_x(); | ||
| } | ||
| return *_cell_area_xhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_xhigh;
^ |
||
| } | ||
| FieldMetric& cell_area_ylow() { | ||
| if (!_cell_area_ylow.has_value()) { | ||
| _compute_cell_area_y(); | ||
| } | ||
| return *_cell_area_ylow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_ylow;
^ |
||
| } | ||
| FieldMetric& cell_area_yhigh() { | ||
| if (!_cell_area_yhigh.has_value()) { | ||
| _compute_cell_area_y(); | ||
| } | ||
| return *_cell_area_yhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_yhigh;
^ |
||
| } | ||
| FieldMetric& cell_area_zlow() { | ||
| if (!_cell_area_zlow.has_value()) { | ||
| _compute_cell_area_z(); | ||
| } | ||
| return *_cell_area_zlow; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_zlow;
^ |
||
| } | ||
| FieldMetric& cell_area_zhigh() { | ||
| if (!_cell_area_zhigh.has_value()) { | ||
| _compute_cell_area_z(); | ||
| } | ||
| return *_cell_area_zhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_area_zhigh;
^ |
||
| } | ||
| // Cell Volume | ||
| const FieldMetric& cell_volume() const { | ||
| if (!_cell_volume.has_value()) { | ||
| _compute_cell_volume(); | ||
| } | ||
| return *_cell_volume; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_volume;
^ |
||
| } | ||
| FieldMetric& cell_volume() { | ||
| if (!_cell_volume.has_value()) { | ||
| _compute_cell_volume(); | ||
| } | ||
| return *_cell_volume; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] return *_cell_volume;
^ |
||
| } | ||
|
|
||
| private: | ||
| mutable std::optional<FieldMetric> _g_22_ylow, _g_22_yhigh; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::optional" is directly included [misc-include-cleaner] include/bout/coordinates.hxx:40: + #include <optional> |
||
| mutable std::optional<FieldMetric> _jxz_ylow, _jxz_yhigh, _jxz_centre; | ||
| mutable std::optional<FieldMetric> _cell_area_xlow, _cell_area_xhigh; | ||
| mutable std::optional<FieldMetric> _cell_area_ylow, _cell_area_yhigh; | ||
| mutable std::optional<FieldMetric> _cell_area_zlow, _cell_area_zhigh; | ||
| mutable std::optional<FieldMetric> _cell_volume; | ||
| void _compute_Jxz_cell_faces() const; | ||
| void _compute_cell_area_x() const; | ||
| void _compute_cell_area_y() const; | ||
| void _compute_cell_area_z() const; | ||
| void _compute_cell_volume() const; | ||
|
|
||
| public: | ||
| /// Christoffel symbol of the second kind (connection coefficients) | ||
| FieldMetric G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; | ||
| FieldMetric G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; | ||
|
|
@@ -256,10 +363,10 @@ private: | |
| class TokamakCoordinates : public Coordinates { | ||
| public: | ||
| TokamakCoordinates(Mesh *mesh) : Coordinates(mesh) { | ||
|
|
||
| } | ||
| private: | ||
|
|
||
| }; | ||
| */ | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,9 @@ | |
| #include <bout/build_defines.hxx> | ||
| #include <bout/constants.hxx> | ||
| #include <bout/coordinates.hxx> | ||
| #include <bout/field.hxx> | ||
| #include <bout/output.hxx> | ||
| #include <bout/region.hxx> | ||
| #include <bout/sys/timer.hxx> | ||
| #include <bout/utils.hxx> | ||
|
|
||
|
|
@@ -1878,7 +1880,7 @@ Field2D Coordinates::Laplace_perpXY([[maybe_unused]] const Field2D& A, | |
|
|
||
| const Coordinates::FieldMetric& Coordinates::invSg() const { | ||
| if (invSgCache == nullptr) { | ||
| auto ptr = std::make_unique<FieldMetric>(); | ||
| auto ptr = std::make_unique<Coordinates::FieldMetric>(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::make_unique" is directly included [misc-include-cleaner] auto ptr = std::make_unique<Coordinates::FieldMetric>();
^ |
||
| (*ptr) = 1.0 / sqrt(g_22); | ||
| invSgCache = std::move(ptr); | ||
| } | ||
|
|
@@ -1898,7 +1900,7 @@ Coordinates::Grad2_par2_DDY_invSg(CELL_LOC outloc, const std::string& method) co | |
| invSgCache->applyParallelBoundary("parallel_neumann_o2"); | ||
|
|
||
| // cache | ||
| auto ptr = std::make_unique<FieldMetric>(); | ||
| auto ptr = std::make_unique<Coordinates::FieldMetric>(); | ||
| *ptr = DDY(*invSgCache, outloc, method) * invSg(); | ||
| Grad2_par2_DDY_invSgCache[method] = std::move(ptr); | ||
| return *Grad2_par2_DDY_invSgCache[method]; | ||
|
|
@@ -2007,3 +2009,130 @@ void Coordinates::checkContravariant() { | |
| } | ||
| } | ||
| } | ||
|
|
||
| const Coordinates::FieldMetric& Coordinates::g_22_ylow() const { | ||
| if (_g_22_ylow.has_value()) { | ||
| return *_g_22_ylow; | ||
| } | ||
| _g_22_ylow.emplace(emptyFrom(g_22)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "emptyFrom" is directly included [misc-include-cleaner] _g_22_ylow.emplace(emptyFrom(g_22));
^ |
||
| //_g_22_ylow->setLocation(CELL_YLOW); | ||
| auto* mesh = Bxy.getMesh(); | ||
| if (Bxy.isFci()) { | ||
| if (mesh->get(_g_22_ylow.value(), "g_22_cell_ylow", 0.0, false) != 0) { | ||
| throw BoutException("The grid file does not contain `g_22_cell_ylow`."); | ||
| } | ||
| } else { | ||
| ASSERT0(mesh->ystart > 0); | ||
| BOUT_FOR(i, g_22.getRegion("RGN_NOY")) { | ||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _g_22_ylow.value()[i] = SQ(0.5 * (sqrt(g_22[i]) + sqrt(g_22[i.ym()]))); | ||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| return g_22_ylow(); | ||
| } | ||
|
|
||
| const Coordinates::FieldMetric& Coordinates::g_22_yhigh() const { | ||
| if (_g_22_yhigh.has_value()) { | ||
| return *_g_22_yhigh; | ||
| } | ||
| _g_22_yhigh.emplace(emptyFrom(g_22)); | ||
| //_g_22_yhigh->setLocation(CELL_YHIGH); | ||
| auto* mesh = Bxy.getMesh(); | ||
| if (Bxy.isFci()) { | ||
| if (mesh->get(_g_22_yhigh.value(), "g_22_cell_yhigh", 0.0, false) != 0) { | ||
| throw BoutException("The grid file does not contain `g_22_cell_yhigh`."); | ||
| } | ||
| } else { | ||
| ASSERT0(mesh->ystart > 0); | ||
| BOUT_FOR(i, g_22.getRegion("RGN_NOY")) { | ||
| _g_22_yhigh.value()[i] = SQ(0.5 * (sqrt(g_22[i]) + sqrt(g_22[i.yp()]))); | ||
| } | ||
| } | ||
| return g_22_yhigh(); | ||
| } | ||
|
|
||
| void Coordinates::_compute_Jxz_cell_faces() const { | ||
| _jxz_centre.emplace(sqrt(g_11 * g_33 - SQ(g_13))); | ||
| _jxz_ylow.emplace(emptyFrom(_jxz_centre.value())); | ||
| //_jxz_ylow->setLocation(CELL_YLOW); | ||
| _jxz_yhigh.emplace(emptyFrom(_jxz_centre.value())); | ||
| //_jxz_yhigh->setLocation(CELL_YHIGH); | ||
| auto* mesh = _jxz_centre->getMesh(); | ||
| if (Bxy.isFci()) { | ||
| Coordinates::FieldMetric By_c; | ||
| Coordinates::FieldMetric By_h; | ||
| Coordinates::FieldMetric By_l; | ||
| if (mesh->get(By_c, "By", 0.0, false, CELL_CENTRE) != 0) { | ||
| throw BoutException("The grid file does not contain `By`."); | ||
| } | ||
| if (mesh->get(By_l, "By_cell_ylow", 0.0, false) != 0) { | ||
| throw BoutException("The grid file does not contain `By_cell_ylow`."); | ||
| } | ||
| if (mesh->get(By_h, "By_cell_yhigh", 0.0, false) != 0) { | ||
| throw BoutException("The grid file does not contain `By_cell_yhigh`."); | ||
| } | ||
| BOUT_FOR(i, By_c.getRegion("RGN_NOY")) { | ||
| (*_jxz_ylow)[i] = By_c[i] / By_l[i] * (*_jxz_centre)[i]; | ||
| (*_jxz_yhigh)[i] = By_c[i] / By_h[i] * (*_jxz_centre)[i]; | ||
| } | ||
| } else { | ||
| ASSERT0(mesh->ystart > 0); | ||
| BOUT_FOR(i, _jxz_centre->getRegion("RGN_NOY")) { | ||
| (*_jxz_ylow)[i] = 0.5 * ((*_jxz_centre)[i] + (*_jxz_centre)[i.ym()]); | ||
| (*_jxz_yhigh)[i] = 0.5 * ((*_jxz_centre)[i] + (*_jxz_centre)[i.yp()]); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Coordinates::_compute_cell_area_x() const { | ||
| const auto area_centre = sqrt(g_22 * g_33 - SQ(g_23)) * dy * dz; | ||
| _cell_area_xlow.emplace(emptyFrom(area_centre)); | ||
| _cell_area_xhigh.emplace(emptyFrom(area_centre)); | ||
| // We cannot setLocation, as that would trigger the computation of staggered | ||
| // metrics. | ||
| auto* mesh = Bxy.getMesh(); | ||
| ASSERT0(mesh->xstart > 0); | ||
| BOUT_FOR(i, area_centre.getRegion("RGN_NOX")) { | ||
| (*_cell_area_xlow)[i] = 0.5 * (area_centre[i] + area_centre[i.xm()]); | ||
| (*_cell_area_xhigh)[i] = 0.5 * (area_centre[i] + area_centre[i.xp()]); | ||
| } | ||
| } | ||
|
|
||
| void Coordinates::_compute_cell_area_y() const { | ||
| _compute_Jxz_cell_faces(); | ||
| if (_jxz_centre->isFci()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] if (_jxz_centre->isFci()) {
^ |
||
| ASSERT3(isUniform(dx, true, "RGN_ALL")); | ||
| ASSERT2(isUniform(dx, false, "RGN_ALL")); | ||
| ASSERT3(isUniform(dz, true, "RGN_ALL")); | ||
| ASSERT2(isUniform(dz, false, "RGN_ALL")); | ||
| _cell_area_ylow.emplace(*_jxz_ylow * dx * dz); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] _cell_area_ylow.emplace(*_jxz_ylow * dx * dz);
^ |
||
| _cell_area_yhigh.emplace(*_jxz_yhigh * dx * dz); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: unchecked access to optional value [bugprone-unchecked-optional-access] _cell_area_yhigh.emplace(*_jxz_yhigh * dx * dz);
^ |
||
| } else { | ||
| // Field aligned | ||
| const auto area_centre = sqrt(g_11 * g_33 - SQ(g_13)) * dx * dz; | ||
| _cell_area_ylow.emplace(emptyFrom(area_centre)); | ||
| _cell_area_yhigh.emplace(emptyFrom(area_centre)); | ||
| // We cannot setLocation, as that would trigger the computation of staggered | ||
| // metrics. | ||
| auto* mesh = Bxy.getMesh(); | ||
| ASSERT0(mesh->ystart > 0); | ||
| BOUT_FOR(i, mesh->getRegion("RGN_NOY")) { | ||
| (*_cell_area_ylow)[i] = 0.5 * (area_centre[i] + area_centre[i.ym()]); | ||
| (*_cell_area_yhigh)[i] = 0.5 * (area_centre[i] + area_centre[i.yp()]); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Coordinates::_compute_cell_area_z() const { | ||
| const auto area_centre = sqrt(g_11 * g_22 - SQ(g_12)) * dx * dy; | ||
| _cell_area_zlow.emplace(emptyFrom(area_centre)); | ||
| _cell_area_zhigh.emplace(emptyFrom(area_centre)); | ||
| // We cannot setLocation, as that would trigger the computation of staggered | ||
| // metrics. | ||
| //ASSERT0(mesh->zstart > 0); | ||
| BOUT_FOR(i, area_centre.getRegion("RGN_NOZ")) { | ||
| (*_cell_area_zlow)[i] = 0.5 * (area_centre[i] + area_centre[i.zm()]); | ||
| (*_cell_area_zhigh)[i] = 0.5 * (area_centre[i] + area_centre[i.zp()]); | ||
| } | ||
| } | ||
|
|
||
| void Coordinates::_compute_cell_volume() const { _cell_volume.emplace(J * dx * dy * dz); } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably don't need these overloads?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want to add the cell length, both in the cell centre, as well as at the faces, i.e. the distance between the cell centres.
That would replace
g_22then, right now they are still needed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I meant the non-
constones!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need them for normalization. But I am starting to be worried, that that might be a bad idea.
Right now:
gives the correct thing for FCI, but wrong for FA.
works for both
and
works only for FA.
So we probably want to remove write access to the fields, and let BOUT++ handle all of the normalisation. I think that is part of github.com//pull/2873 or #3046 - but that is 900 commits behind next and with its 500 comits has probably more merge conflicts that what I can deal with right now :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#3046 is into #2873 by the way.
We (@tomc271 and myself) can take care of bringing those PRs up-to-date -- can you review them? Starting with #3046
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was waiting for the wrappers that make
coords->dy[i]working again, so not all the code needs to be changed. I thought you still wanted to do that?