Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
ae1f285
Move stencils to separte header
dschwoerer Mar 27, 2024
b9b42ff
Add basic boundary region iterator
dschwoerer Mar 27, 2024
9bdfef5
Provide a new boundary iterator based on RangeIterator
dschwoerer Apr 9, 2024
c51a85f
Only check hasBndry*Y if they would be included
dschwoerer Jul 2, 2024
06d581b
ensure we dont mix non-fci BCs with fci
dschwoerer Jul 5, 2024
7f1d26f
rename to include order
dschwoerer Aug 9, 2024
84f8c83
Fix: remove broken code
dschwoerer Aug 9, 2024
ea05bae
Convert test to new iterator scheeme
dschwoerer Sep 27, 2024
17f8efa
Add Field2D version for 2D metrics
dschwoerer Oct 1, 2024
0db3052
Add setYPrevIfValid
dschwoerer Oct 1, 2024
d2f2cc8
Add offset to parallel boundary region
dschwoerer Jan 13, 2025
1f48a59
Add function to check wehther point is in the boundary
dschwoerer Jan 13, 2025
4af5a4d
Add setValid to BoundaryRegionParIterBase
dschwoerer Jan 13, 2025
e5fbcaf
Reimplement ynext for the boundary region
dschwoerer Jan 13, 2025
ef7b03d
Fix extrapolaton / interpolation
dschwoerer Jan 13, 2025
6dba751
Fix parallel boundary to interpolate into the boundary
dschwoerer Jan 13, 2025
f105c3f
Ensure data is sorted
dschwoerer Jan 13, 2025
f7c1aca
Calculate valid for the general case
dschwoerer Jan 13, 2025
55bdbcf
fix parallel neumann BC
dschwoerer Jan 20, 2025
6f40b4e
Add limitFree
dschwoerer Jan 20, 2025
36c1f94
add setAll to parallel BC
dschwoerer Jan 20, 2025
c7cbf11
Move yboundary iterator from hermes to BOUT++
dschwoerer Jan 31, 2025
f9cad29
Add iter_pnts function
dschwoerer Mar 3, 2025
e6f004b
Add example on how to replace RangeIterator with YBoundary
dschwoerer Mar 3, 2025
3a0f214
Move documentation to sphinx
dschwoerer Mar 3, 2025
4e21aac
Fix iter_pnts
dschwoerer Mar 4, 2025
3a850b1
Add more documentation on YBoundary
dschwoerer Mar 4, 2025
e0f80cf
Ensure the field has parallel slices
dschwoerer Mar 7, 2025
101f33d
Lower check level
dschwoerer Mar 7, 2025
4ea1657
Prefer std::vector::emplace_back to work around cuda compiler issue
dschwoerer Aug 21, 2025
c78dd6e
Apply clang-format changes
dschwoerer Aug 21, 2025
6fadc06
remove unneeded std::move
dschwoerer Aug 21, 2025
2129820
Add limit_at_least function to boundary_iterator
dschwoerer Sep 1, 2025
7fc08a3
Interpolate sheath is at least o2
dschwoerer Oct 21, 2025
e135545
Interpolate sheath is at least o2
dschwoerer Oct 21, 2025
73e4183
Add limitFreeScale and SheathLimitMode
dschwoerer Oct 21, 2025
4c105b8
Add extrapolate_sheath_free
dschwoerer Oct 21, 2025
41f9b28
Add set_free
dschwoerer Oct 21, 2025
e1364b3
add missing interpolate_sheath_o2(func) to FA
dschwoerer Oct 22, 2025
2edebb3
add is_lower() to check for which direction the boundary is
dschwoerer Oct 22, 2025
3821205
Only call iterateBndryLowerY() for non-FCI
dschwoerer Jan 21, 2026
38293b9
Break include cycle
dschwoerer Mar 4, 2026
6ae2351
Fix Field3D::setBoundaryTo for FCI methods
dschwoerer Mar 10, 2026
576c609
Copy BCs in x-direction also for FCI
dschwoerer Nov 25, 2024
1b99b34
Use consistently first order interpolation
dschwoerer Nov 25, 2024
ff190e8
Add option to copy parallel slices at setBoundaryTo
dschwoerer Mar 10, 2026
6aac834
Prefer [[maybe_unused]]
dschwoerer Mar 4, 2026
d5fb4c4
Fixup parallel_boundary
dschwoerer Mar 4, 2026
4b503c5
Ensure init is only called once
dschwoerer Mar 6, 2026
e9a0944
Add headers from clang-tidy
dschwoerer Mar 9, 2026
c59626a
[bot] Apply format changes
dschwoerer Mar 10, 2026
2c4179d
[bot] Add last format changes commit to ignore file
dschwoerer Mar 10, 2026
7178646
Apply clang-tidy fixes
dschwoerer Mar 10, 2026
7975518
Add missing header
dschwoerer Mar 10, 2026
4ee3d9d
Add contains to YBoundary
dschwoerer Mar 11, 2026
44fd331
Do not use else after return
dschwoerer Mar 11, 2026
e94bb27
Ensure YBoundary can compile
dschwoerer Mar 11, 2026
f26bbfb
Add test for YBoundary
dschwoerer Mar 11, 2026
52cb85a
Apply clang-tidy suggestions
dschwoerer Mar 11, 2026
a367a21
Merge branch 'next' into new-par-bc-unified
dschwoerer Mar 12, 2026
6d72a7e
Use std::ranges::any_of
dschwoerer Mar 12, 2026
138f20b
Merge branch 'next' of github.com:boutproject/BOUT-dev into HEAD
dschwoerer Mar 12, 2026
5968f13
Fixes for prek
dschwoerer Mar 12, 2026
ade82b7
Fix usage of any_of
dschwoerer Mar 12, 2026
8872cd2
Merge branch 'next' of github.com:boutproject/BOUT-dev into new-par-b…
dschwoerer Mar 13, 2026
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
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ d1cfb8abd6aa5c76e6c1a4d7ab20929c65f8afc2
8d5cb39e03c2644715a50684f8cd0318b4e82676
ec69e8838be2dde140a915e50506f8e1ce3cb534
f2bc0488a298f136294c523bc5ab4086d090059b
c59626a0498b0cfd1be46f84f0fa38b4855a43cc
1b4707187a3a85126338303dc766280b8fb2dc56
b2e2f3575e68f771be2a4341af5fd14e2870469e
64e4285ec38569f66d31e589a4610cefd16d8076
218 changes: 218 additions & 0 deletions include/bout/boundary_iterator.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#pragma once

#include "bout/assert.hxx"
#include "bout/bout_types.hxx"
#include "bout/build_defines.hxx"
#include "bout/field2d.hxx"
#include "bout/field3d.hxx"
#include "bout/mesh.hxx"
#include "bout/parallel_boundary_region.hxx"
#include "bout/region.hxx"
#include "bout/sys/parallel_stencils.hxx"
#include "bout/sys/range.hxx"
#include <algorithm>
#include <functional>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header utility is not used directly [misc-include-cleaner]

Suggested change

class BoundaryRegionIter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: class 'BoundaryRegionIter' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]

class BoundaryRegionIter {
      ^

public:
virtual ~BoundaryRegionIter() = default;
BoundaryRegionIter(int x, int y, int bx, int by, Mesh* mesh)
: dir(bx + by), x(x), y(y), bx(bx), by(by), localmesh(mesh) {
ASSERT3(bx * by == 0);
}
bool operator!=(const BoundaryRegionIter& rhs) const { return ind() != rhs.ind(); }

Ind3D ind() const { return xyz2ind(x, y, z); }
BoundaryRegionIter& operator++() {
ASSERT3(z < nz());
z++;
if (z == nz()) {
z = 0;
_next();
}
return *this;
}
virtual void _next() = 0;
BoundaryRegionIter& operator*() { return *this; }

void dirichlet_o2(Field3D& f, BoutReal value) const {
ynext(f) = parallel_stencil::dirichlet_o2(1, f[ind()], 0.5, value);
}

BoutReal extrapolate_grad_o2(const Field3D& f) const { return f[ind()] - yprev(f); }

BoutReal extrapolate_sheath_o2(const Field3D& f) const {
return (f[ind()] * 3 - yprev(f)) * 0.5;
}

BoutReal extrapolate_next_o2(const Field3D& f) const {
return (2 * f[ind()]) - yprev(f);
}

BoutReal
extrapolate_next_o2(const std::function<BoutReal(int yoffset, Ind3D ind)>& f) const {
return (2 * f(0, ind())) - f(0, ind().yp(-by).xp(-bx));
}

BoutReal interpolate_sheath_o2(const Field3D& f) const {
return (f[ind()] + ynext(f)) * 0.5;
}

BoutReal
interpolate_sheath_o2(const std::function<BoutReal(int yoffset, Ind3D ind)>& f) const {
return (f(0, ind()) + f(0, ind().yp(-by).xp(-bx))) * 0.5;
}

BoutReal
extrapolate_sheath_o2(const std::function<BoutReal(int yoffset, Ind3D ind)>& f) const {
return 0.5 * (3 * f(0, ind()) - f(0, ind().yp(-by).xp(-bx)));
}

BoutReal extrapolate_sheath_free(const Field3D& f, SheathLimitMode mode) const {
const BoutReal fac =
bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f), mode);
const BoutReal val = ythis(f);
const BoutReal next = mode == SheathLimitMode::linear_free ? val + fac : val * fac;
return 0.5 * (val + next);
}

void set_free(Field3D& f, SheathLimitMode mode) const {
const BoutReal fac =
bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f), mode);
BoutReal val = ythis(f);
if (mode == SheathLimitMode::linear_free) {
for (int i = 1; i <= localmesh->ystart; ++i) {
val += fac;
f[ind().yp(by * i).xp(bx * i)] = val;
}
} else {
for (int i = 1; i <= localmesh->ystart; ++i) {
val *= fac;
f[ind().yp(by * i).xp(bx * i)] = val;
}
}
}

void limitFree(Field3D& f) const {
const BoutReal fac =
bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f));
BoutReal val = ythis(f);
for (int i = 1; i <= localmesh->ystart; ++i) {
val *= fac;
f[ind().yp(by * i).xp(bx * i)] = val;
}
}

bool is_lower() const {
ASSERT2(bx == 0);
return by == -1;
}

void neumann_o1(Field3D& f, BoutReal grad) const {
BoutReal val = ythis(f);
for (int i = 1; i <= localmesh->ystart; ++i) {
val += grad;
f[ind().yp(by * i).xp(bx * i)] = val;
}
}

void neumann_o2(Field3D& f, BoutReal grad) const {
BoutReal val = yprev(f) + grad;
for (int i = 1; i <= localmesh->ystart; ++i) {
val += grad;
f[ind().yp(by * i).xp(bx * i)] = val;
}
}

void limit_at_least(Field3D& f, BoutReal value) const {
ynext(f) = std::max(ynext(f), value);
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::max" is directly included [misc-include-cleaner]

include/bout/boundary_iterator.hxx:12:

- #include <functional>
+ #include <algorithm>
+ #include <functional>

}

BoutReal& ynext(Field3D& f) const { return f[ind().yp(by).xp(bx)]; }
const BoutReal& ynext(const Field3D& f) const { return f[ind().yp(by).xp(bx)]; }
BoutReal& yprev(Field3D& f) const { return f[ind().yp(-by).xp(-bx)]; }
const BoutReal& yprev(const Field3D& f) const { return f[ind().yp(-by).xp(-bx)]; }
BoutReal& ythis(Field3D& f) const { return f[ind()]; }
const BoutReal& ythis(const Field3D& f) const { return f[ind()]; }

void setYPrevIfValid(Field3D& f, BoutReal val) const { yprev(f) = val; }
void setAll(Field3D& f, const BoutReal val) const {
for (int i = -localmesh->ystart; i <= localmesh->ystart; ++i) {
f[ind().yp(by * i).xp(bx * i)] = val;
}
}

static int abs_offset() { return 1; }

#if BOUT_USE_METRIC_3D == 0
BoutReal& ynext(Field2D& f) const { return f[ind().yp(by).xp(bx)]; }
const BoutReal& ynext(const Field2D& f) const { return f[ind().yp(by).xp(bx)]; }
BoutReal& yprev(Field2D& f) const { return f[ind().yp(-by).xp(-bx)]; }
const BoutReal& yprev(const Field2D& f) const { return f[ind().yp(-by).xp(-bx)]; }
#endif

const int dir;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member 'dir' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]

  const int dir;
            ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'dir' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  const int dir;
            ^


protected:
int z{0};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'z' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  int z{0};
      ^

int x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'x' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  int x;
      ^

int y;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'y' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  int y;
      ^

const int bx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member 'bx' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]

  const int bx;
            ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'bx' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  const int bx;
            ^

const int by;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member 'by' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]

  const int by;
            ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'by' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  const int by;
            ^


private:
Mesh* localmesh;
int nx() const { return localmesh->LocalNx; }
int ny() const { return localmesh->LocalNy; }
int nz() const { return localmesh->LocalNz; }

Ind3D xyz2ind(int x, int y, int z) const {
return Ind3D{((x * ny() + y) * nz()) + z, ny(), nz()};
}
};

class BoundaryRegionIterY : public BoundaryRegionIter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: destructor of 'BoundaryRegionIterY' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]

class BoundaryRegionIterY : public BoundaryRegionIter {
      ^
Additional context

include/bout/boundary_iterator.hxx:164: make it public and virtual

class BoundaryRegionIterY : public BoundaryRegionIter {
      ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: class 'BoundaryRegionIterY' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]

class BoundaryRegionIterY : public BoundaryRegionIter {
      ^

public:
~BoundaryRegionIterY() override = default;
BoundaryRegionIterY(const RangeIterator& r, int y, int dir, bool is_end, Mesh* mesh)
: BoundaryRegionIter(r.ind, y, 0, dir, mesh), r(r), is_end(is_end) {}

bool operator!=(const BoundaryRegionIterY& rhs) {
ASSERT2(y == rhs.y);
if (is_end) {
if (rhs.is_end) {
return false;
}
return !rhs.r.isDone();
}
if (rhs.is_end) {
return !r.isDone();
}
return x != rhs.x;
}

void _next() override {
++r;
x = r.ind;
}

private:
RangeIterator r;
bool is_end;
};

class NewBoundaryRegionY {
public:
NewBoundaryRegionY(Mesh* mesh, bool lower, const RangeIterator& r)
: mesh(mesh), lower(lower), r(r) {}
BoundaryRegionIterY begin(bool begin = true) {
return BoundaryRegionIterY(r, lower ? mesh->ystart : mesh->yend, lower ? -1 : +1,
!begin, mesh);
}
BoundaryRegionIterY end() { return begin(false); }

private:
Mesh* mesh;
bool lower;
RangeIterator r;
};
3 changes: 2 additions & 1 deletion include/bout/field3d.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,8 @@ public:
/// This uses 2nd order central differences to set the value
/// on the boundary to the value on the boundary in field \p f3d.
/// Note: does not just copy values in boundary region.
void setBoundaryTo(const Field3D& f3d);
void setBoundaryTo(const Field3D& f3d) { setBoundaryTo(f3d, true); }
void setBoundaryTo(const Field3D& f3d, bool copyParallelSlices);

using FieldData::applyParallelBoundary;
void applyParallelBoundary() override;
Expand Down
41 changes: 24 additions & 17 deletions include/bout/parallel_boundary_op.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected:
enum class ValueType { GEN, FIELD, REAL };
const ValueType value_type{ValueType::REAL};

BoutReal getValue(const BoundaryRegionPar& bndry, BoutReal t);
BoutReal getValue(const BoundaryRegionParIter& bndry, BoutReal t);
};

template <class T, bool isNeumann = false>
Expand Down Expand Up @@ -95,12 +95,13 @@ public:

auto dy = f.getCoordinates()->dy;

for (bndry->first(); !bndry->isDone(); bndry->next()) {
BoutReal value = getValue(*bndry, t);
for (auto pnt : *bndry) {
//for (bndry->first(); !bndry->isDone(); bndry->next()) {
BoutReal value = getValue(pnt, t);
if (isNeumann) {
value *= dy[bndry->ind()];
value *= dy[pnt.ind()];
}
static_cast<T*>(this)->apply_stencil(f, bndry, value);
static_cast<T*>(this)->apply_stencil(f, pnt, value);
}
}
};
Expand All @@ -111,51 +112,57 @@ public:
class BoundaryOpPar_dirichlet_o1 : public BoundaryOpParTemp<BoundaryOpPar_dirichlet_o1> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->dirichlet_o1(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.dirichlet_o1(f, value);
}
};

class BoundaryOpPar_dirichlet_o2 : public BoundaryOpParTemp<BoundaryOpPar_dirichlet_o2> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->dirichlet_o2(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.dirichlet_o2(f, value);
}
};

class BoundaryOpPar_dirichlet_o3 : public BoundaryOpParTemp<BoundaryOpPar_dirichlet_o3> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->dirichlet_o3(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.dirichlet_o3(f, value);
}
};

class BoundaryOpPar_neumann_o1
: public BoundaryOpParTemp<BoundaryOpPar_neumann_o1, true> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->neumann_o1(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.neumann_o1(f, value);
}
};

class BoundaryOpPar_neumann_o2
: public BoundaryOpParTemp<BoundaryOpPar_neumann_o2, true> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->neumann_o2(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.neumann_o2(f, value);
}
};

class BoundaryOpPar_neumann_o3
: public BoundaryOpParTemp<BoundaryOpPar_neumann_o3, true> {
public:
using BoundaryOpParTemp::BoundaryOpParTemp;
static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) {
bndry->neumann_o3(f, value);
static void apply_stencil(Field3D& f, const BoundaryRegionParIter& pnt,
BoutReal value) {
pnt.neumann_o3(f, value);
}
};

Expand Down
Loading
Loading