Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 112 additions & 5 deletions include/bout/coordinates.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -38,6 +38,7 @@
#include <bout/field2d.hxx>
#include <bout/field3d.hxx>
#include <bout/paralleltransform.hxx>
#include <optional>

class Mesh;

Expand Down Expand Up @@ -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();
Comment on lines +109 to +110
Copy link
Member

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?

Copy link
Contributor Author

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_22 then, right now they are still needed.

Copy link
Member

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-const ones!

Copy link
Contributor Author

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:

coords->g_22 *= norm;
coords->g_22_ylow() *= norm;
coords->g_22_yhigh() *= norm;

gives the correct thing for FCI, but wrong for FA.

works for both
and

coords->g_22 *= norm;
coords->g_22_ylow();
coords->g_22_yhigh();

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 :-(

Copy link
Member

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

Copy link
Contributor Author

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?

// Cell Areas
const FieldMetric& cell_area_xlow() const {
if (!_cell_area_xlow.has_value()) {
_compute_cell_area_x();
}
return *_cell_area_xlow;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
Expand Down Expand Up @@ -256,10 +363,10 @@ private:
class TokamakCoordinates : public Coordinates {
public:
TokamakCoordinates(Mesh *mesh) : Coordinates(mesh) {

}
private:

};
*/

Expand Down
3 changes: 3 additions & 0 deletions include/bout/field2d.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ public:

int size() const override { return nx * ny; }

Field2D& asField3DParallel() { return *this; }
const Field2D& asField3DParallel() const { return *this; }

private:
/// Internal data array. Handles allocation/freeing of memory
Array<BoutReal> data;
Expand Down
133 changes: 131 additions & 2 deletions src/mesh/coordinates.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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>();
Copy link
Contributor

Choose a reason for hiding this comment

The 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);
}
Expand All @@ -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];
Expand Down Expand Up @@ -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));
Copy link
Contributor

Choose a reason for hiding this comment

The 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")) {
_g_22_ylow.value()[i] = SQ(0.5 * (sqrt(g_22[i]) + sqrt(g_22[i.ym()])));
}
}
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()) {
Copy link
Contributor

Choose a reason for hiding this comment

The 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);
Copy link
Contributor

Choose a reason for hiding this comment

The 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);
Copy link
Contributor

Choose a reason for hiding this comment

The 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); }
Loading
Loading