Skip to content

WIP: Lazy stencil expressions for kernel fusion - #3401

Open
bendudson wants to merge 19 commits into
nextfrom
lazy-stencil-operators
Open

WIP: Lazy stencil expressions for kernel fusion#3401
bendudson wants to merge 19 commits into
nextfrom
lazy-stencil-operators

Conversation

@bendudson

@bendudson bendudson commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Operators return BinaryExpr types that perform derivatives 'lazily'. Like the single index operators they capture a CoordinatesAccessor to provide access to metrics etc. The difference is that the user code doesn't need to create field accessors or explicitly write the loop, capture variables etc. All that is done automatically if the compiler is smart/sufficiently aggressively optimizing.

Implemented DDZ_C2 and DDZ_C4 operators for Z derivatives. These appear to inline as expected in the Hasegawa-Wakatani example.

The DDZ(Field3D) operator now returns a lazy BinaryExpr type. It still allows runtime choice of numerical method (C2 / C4) and staggered fields.

Return BinaryExpr types, perform derivatives in Z
using CoordinateAccessor to get dz.

Appear to inline in Hasegawa-Wakatani example.
@bendudson bendudson added the work in progress Not ready for merging label Jun 21, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread examples/hasegawa-wakatani/hw.cxx Outdated
int nz{0};

template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,

Copy link
Copy Markdown
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 "BOUT_FORCEINLINE" is directly included [misc-include-cleaner]

  BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
                   ^

Comment thread include/bout/stencil_expr.hxx
Comment thread include/bout/stencil_expr.hxx

template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {

inline bout::stencil::DDZExprC2 DDZ_C2(const Field3D& f) {
checkData(f);

const auto region_id = f.getMesh()->getRegionID("RGN_NOBNDRY");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

  const auto region_id = f.getMesh()->getRegionID("RGN_NOBNDRY");
                                    ^
Additional context

include/bout/field_data.hxx:47: forward declaration of 'Mesh'

class Mesh;
      ^

f.getLocation(),
f.getDirections(),
region_id,
f.getMesh()->getRegion("RGN_NOBNDRY")};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

      f.getMesh()->getRegion("RGN_NOBNDRY")};
                 ^
Additional context

include/bout/field_data.hxx:47: forward declaration of 'Mesh'

class Mesh;
      ^

inline bout::stencil::DDZExprC4 DDZ_C4(const Field3D& f) {
checkData(f);

const auto region_id = f.getMesh()->getRegionID("RGN_NOBNDRY");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

  const auto region_id = f.getMesh()->getRegionID("RGN_NOBNDRY");
                                    ^
Additional context

include/bout/field_data.hxx:47: forward declaration of 'Mesh'

class Mesh;
      ^

f.getLocation(),
f.getDirections(),
region_id,
f.getMesh()->getRegion("RGN_NOBNDRY")};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

      f.getMesh()->getRegion("RGN_NOBNDRY")};
                 ^
Additional context

include/bout/field_data.hxx:47: forward declaration of 'Mesh'

class Mesh;
      ^

Implements Arakawa bracket in X-Z as a BinaryExpr.
Testing the performance impact of runtime dispatch. The hope is to
preserve the ability to switch method at runtime.  The conditional
that selects the method is the same for all iterations, so hopefully
good branch prediction and no warp divergence.

DDZ_Dispatch(f, method) selects between DDZ_C2 and DDZ_C4 at runtime.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread examples/hasegawa-wakatani/hw.cxx
Comment thread examples/hasegawa-wakatani/hw.cxx Outdated
ddt(n) =
-bracket(phi, n, bm) + alpha * (nonzonal_phi - nonzonal_n) - kappa * DDZ(phi);
ddt(n) = -bracket_arakawa(phi, n) + alpha * (nonzonal_phi - nonzonal_n)
- kappa * DDZ_Dispatch(phi, DIFF_C2);

Copy link
Copy Markdown
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 "DIFF_C2" is directly included [misc-include-cleaner]

             - kappa * DDZ_Dispatch(phi, DIFF_C2);
                                         ^

struct DDZ_Dispatch_Op {
CoordinatesAccessor coords;
int nz{0};
DIFF_METHOD method{DIFF_DEFAULT};

Copy link
Copy Markdown
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 "DIFF_DEFAULT" is directly included [misc-include-cleaner]

  DIFF_METHOD method{DIFF_DEFAULT};
                     ^

struct DDZ_Dispatch_Op {
CoordinatesAccessor coords;
int nz{0};
DIFF_METHOD method{DIFF_DEFAULT};

Copy link
Copy Markdown
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 "DIFF_METHOD" is directly included [misc-include-cleaner]

  DIFF_METHOD method{DIFF_DEFAULT};
  ^


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {

BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {
switch (method) {
case DIFF_C2:

Copy link
Copy Markdown
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 "DIFF_C2" is directly included [misc-include-cleaner]

    case DIFF_C2:
         ^

switch (method) {
case DIFF_C2:
return apply_c2(idx, lhs);
case DIFF_C4:

Copy link
Copy Markdown
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 "DIFF_C4" is directly included [misc-include-cleaner]

    case DIFF_C4:
         ^


if ((method != DIFF_C2) && (method != DIFF_C4)) {
throw BoutException("DDZ_Dispatch only supports DIFF_C2 and DIFF_C4, got {:s}",
toString(method));

Copy link
Copy Markdown
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 "toString" is directly included [misc-include-cleaner]

                        toString(method));
                        ^

const Field3D& g) {
checkData(f);
checkData(g);
ASSERT1_FIELDS_COMPATIBLE(f, g);

Copy link
Copy Markdown
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 "ASSERT1_FIELDS_COMPATIBLE" is directly included [misc-include-cleaner]

include/bout/stencil_expr.hxx:1:

- #ifndef BOUT_STENCIL_EXPR_HXX
+ #include "bout/field2d.hxx"
+ #ifndef BOUT_STENCIL_EXPR_HXX

Retains the runtime dispatch of DDZ, while building a BinaryExpr
lazy expression.
Stores the default numerical methods as DIFF_METHOD enums. This
enables runtime dispatch with minimal overhead in expressions.
Retains runtime choice of method, and handling of staggered inputs or
outputs. Only C2 and C4 methods are supported.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 52. Check the log or trigger a new build to see more.

ITERATOR_TEST_BLOCK("DDZ Default", result = DDZ(a););

ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, "DIFF_C2"););
ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););

Copy link
Copy Markdown
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 "CELL_DEFAULT" is directly included [misc-include-cleaner]

  ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););
                                                ^

ITERATOR_TEST_BLOCK("DDZ Default", result = DDZ(a););

ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, "DIFF_C2"););
ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););

Copy link
Copy Markdown
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 "DIFF_C2" is directly included [misc-include-cleaner]

  ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););
                                                              ^

ITERATOR_TEST_BLOCK("DDZ Default", result = DDZ(a););

ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, "DIFF_C2"););
ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: variable 'start' of type 'SteadyClock' (aka 'time_pointstd::chrono::steady_clock') can be declared 'const' [misc-const-correctness]

  ITERATOR_TEST_BLOCK("DDZ C2", result = DDZ(a, CELL_DEFAULT, DIFF_C2););
  ^
Additional context

examples/performance/ddz/ddz.cxx:27: expanded from macro 'ITERATOR_TEST_BLOCK'

    SteadyClock start = steady_clock::now();                                        \
    ^

ITERATOR_TEST_BLOCK("DDZ W3", result = DDZ(a, CELL_DEFAULT, "DIFF_W3"););

ITERATOR_TEST_BLOCK("DDZ FFT", result = DDZ(a, CELL_DEFAULT, "DIFF_FFT"););
ITERATOR_TEST_BLOCK("DDZ C4", result = DDZ(a, CELL_DEFAULT, DIFF_C4););

Copy link
Copy Markdown
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 "DIFF_C4" is directly included [misc-include-cleaner]

  ITERATOR_TEST_BLOCK("DDZ C4", result = DDZ(a, CELL_DEFAULT, DIFF_C4););
                                                              ^

ITERATOR_TEST_BLOCK("DDZ W3", result = DDZ(a, CELL_DEFAULT, "DIFF_W3"););

ITERATOR_TEST_BLOCK("DDZ FFT", result = DDZ(a, CELL_DEFAULT, "DIFF_FFT"););
ITERATOR_TEST_BLOCK("DDZ C4", result = DDZ(a, CELL_DEFAULT, DIFF_C4););

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: variable 'start' of type 'SteadyClock' (aka 'time_pointstd::chrono::steady_clock') can be declared 'const' [misc-const-correctness]

  ITERATOR_TEST_BLOCK("DDZ C4", result = DDZ(a, CELL_DEFAULT, DIFF_C4););
  ^
Additional context

examples/performance/ddz/ddz.cxx:27: expanded from macro 'ITERATOR_TEST_BLOCK'

    SteadyClock start = steady_clock::now();                                        \
    ^

Comment thread include/bout/mesh.hxx
static constexpr int num_staggers = 3;
static constexpr int num_deriv_kinds = 5;

std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: performing an implicit widening conversion to type 'std::size_t' (aka 'unsigned long') of a multiplication performed in type 'int' [bugprone-implicit-widening-of-multiplication-result]

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^
Additional context

include/bout/mesh.hxx:103: make conversion explicit to silence this warning

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^

include/bout/mesh.hxx:103: perform multiplication in a wider type

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^

Comment thread include/bout/mesh.hxx

DIFF_METHOD get(DIRECTION direction, DERIV deriv,
STAGGER stagger = STAGGER::None) const {
return values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]

      return values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))
             ^

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think values.at() suppresses this warning

Comment thread include/bout/mesh.hxx
DIFF_METHOD get(DIRECTION direction, DERIV deriv,
STAGGER stagger = STAGGER::None) const {
return values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))
* num_deriv_kinds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

Suggested change
* num_deriv_kinds
return values[((directionIndex(direction) * num_staggers + staggerIndex(stagger))
* num_deriv_kinds)

Comment thread include/bout/mesh.hxx

void set(DIRECTION direction, DERIV deriv, DIFF_METHOD method,
STAGGER stagger = STAGGER::None) {
values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]

      values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))
      ^

Comment thread include/bout/mesh.hxx
void set(DIRECTION direction, DERIV deriv, DIFF_METHOD method,
STAGGER stagger = STAGGER::None) {
values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))
* num_deriv_kinds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

Suggested change
* num_deriv_kinds
values[((directionIndex(direction) * num_staggers + staggerIndex(stagger))
* num_deriv_kinds)

@ZedThree ZedThree left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this intended as a replacement for the existing derivatives generation machinery?

Comment thread include/bout/field.hxx Outdated
Comment on lines +551 to +554
template <typename ResT, typename L, typename R, typename Func>
struct expression_result<BinaryExpr<ResT, L, R, Func>> {
using type = ResT;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be clearer to consistently just use Result instead of ResT? It took me a minute to decipher that

Comment thread include/bout/mesh.hxx
Comment on lines +100 to +102
static constexpr int num_directions = 3;
static constexpr int num_staggers = 3;
static constexpr int num_deriv_kinds = 5;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Making these std::size_t might fix a bunch of the clang-tidy warnings?

Comment thread include/bout/mesh.hxx
}
}

static DIFF_METHOD builtinDefaultMethod(DERIV deriv) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think these can be also be constexpr

Comment thread include/bout/mesh.hxx
case DERIV::Flux:
return DIFF_U1;
}
throw BoutException("Unhandled derivative kind in builtinDefaultMethod");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could use something like C++23's std::unreachable instead here

Comment thread include/bout/mesh.hxx

DIFF_METHOD get(DIRECTION direction, DERIV deriv,
STAGGER stagger = STAGGER::None) const {
return values[(directionIndex(direction) * num_staggers + staggerIndex(stagger))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think values.at() suppresses this warning

case STAGGER::L2C:
return apply_c2_l2c(idx, lhs);
}
return 0.0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could also use an unreachable() function

@bendudson

Copy link
Copy Markdown
Contributor Author

Is this intended as a replacement for the existing derivatives generation machinery?

Hi @ZedThree ! Yes, this would replace the index_derivs machinery. The current kernels are optimized for CPUs but are too small to run efficiently on GPUs. To have any chance of running on GPUs efficiently, kernels need to be merged into larger expressions. The single index operators were one way, but these template expressions hide a lot of the ceremony of creating field accessors, capturing variables etc. The interface stays essentially the same, apart from explicitly converting BinaryExpr to fields in some places.

@bendudson bendudson added the GPU label Aug 27, 2026
Merge the lazy `pow` implementation.

Add a `DDZ_FFT` function for when FFT is needed.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 30. Check the log or trigger a new build to see more.

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:113: the definition seen here

Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, DIFF_METHOD method,
         ^

include/bout/derivs.hxx:150: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector2D DDZ(const Vector2D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:149: the definition seen here

Vector2D DDZ(const Vector2D& v, CELL_LOC UNUSED(outloc), DIFF_METHOD UNUSED(method),
         ^

include/bout/derivs.hxx:171: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread include/bout/field.hxx
BinaryExpr<FieldPerp, L, R, bout::op::Pow>>
pow(const L& lhs, const R& rhs) {
ASSERT1_EXPR_COMPATIBLE(lhs, rhs);
ASSERT1(lhs.getIndex() == rhs.getIndex());

Copy link
Copy Markdown
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 "ASSERT1" is directly included [misc-include-cleaner]

;
    ^

Comment thread include/bout/mesh.hxx
static constexpr int num_staggers = 3;
static constexpr int num_deriv_kinds = 5;

std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: performing an implicit widening conversion to type 'std::size_t' (aka 'unsigned long') of a multiplication performed in type 'int' [bugprone-implicit-widening-of-multiplication-result]

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^
Additional context

include/bout/mesh.hxx:104: make conversion explicit to silence this warning

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^

include/bout/mesh.hxx:104: perform multiplication in a wider type

    std::array<DIFF_METHOD, num_directions * num_staggers * num_deriv_kinds> values{};
                            ^

Comment thread include/bout/mesh.hxx
BoutReal fft_derivs_filter{0.0};

/// Concrete default methods initialised from options in derivs_init
DerivativeDefaults derivative_defaults{};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: initializer for member 'derivative_defaults' is redundant [readability-redundant-member-init]

Suggested change
DerivativeDefaults derivative_defaults{};
DerivativeDefaults derivative_defaults;

Comment thread src/mesh/index_derivs.cxx
return DIFF_S2;
}
if (method == "DEFAULT") {
throw BoutException("Default derivative options must resolve to a concrete method");

Copy link
Copy Markdown
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 "BoutException" is directly included [misc-include-cleaner]

src/mesh/index_derivs.cxx:22:

- #include "bout/build_defines.hxx"
+ #include "bout/boutexception.hxx"
+ #include "bout/build_defines.hxx"

Comment thread src/mesh/index_derivs.cxx
DerivativeStore<Field3D>::getInstance().initialise(options);
DerivativeStore<Field2D>::getInstance().initialise(options);

auto backup_section = options->getSection("diff");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: 'auto backup_section' can be declared as 'auto *backup_section' [readability-qualified-auto]

Suggested change
auto backup_section = options->getSection("diff");
auto *backup_section = options->getSection("diff");

Comment thread src/mesh/index_derivs.cxx
DerivativeStore<Field2D>::getInstance().initialise(options);

auto backup_section = options->getSection("diff");
const std::array<std::pair<DIRECTION, std::string>, 3> directions{{

Copy link
Copy Markdown
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 "DIRECTION" is directly included [misc-include-cleaner]

  const std::array<std::pair<DIRECTION, std::string>, 3> directions{{
                             ^

Comment thread src/mesh/index_derivs.cxx
DerivativeStore<Field2D>::getInstance().initialise(options);

auto backup_section = options->getSection("diff");
const std::array<std::pair<DIRECTION, std::string>, 3> directions{{

Copy link
Copy Markdown
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::pair" is directly included [misc-include-cleaner]

src/mesh/index_derivs.cxx:32:

+ #include <utility>

Comment thread src/mesh/index_derivs.cxx
{DIRECTION::Y, "ddy"},
{DIRECTION::Z, "ddz"},
}};
const std::array<std::pair<DERIV, std::string>, 5> deriv_types{{

Copy link
Copy Markdown
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 "DERIV" is directly included [misc-include-cleaner]

  const std::array<std::pair<DERIV, std::string>, 5> deriv_types{{
                             ^

Fixes failing serial tests

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

backupSection->get(derivName, theDefault, "");
}

if (uppercase(theDefault) == toString(DIFF_DEFAULT)) {

Copy link
Copy Markdown
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 "uppercase" is directly included [misc-include-cleaner]

include/bout/deriv_store.hxx:39:

- #include <bout/scorepwrapper.hxx>
+ #include "bout/utils.hxx"
+ #include <bout/scorepwrapper.hxx>

Comment thread src/mesh/index_derivs.cxx
derivative_defaults = DerivativeDefaults{};

for (const auto& [direction, section_name] : directions) {
auto specific_section = options->getSection(section_name);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: 'auto specific_section' can be declared as 'auto *specific_section' [readability-qualified-auto]

Suggested change
auto specific_section = options->getSection(section_name);
auto *specific_section = options->getSection(section_name);

Comment thread src/mesh/index_derivs.cxx

for (const auto& [direction, section_name] : directions) {
auto specific_section = options->getSection(section_name);
auto staggered_section = options->getSection(section_name + "stag");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: 'auto staggered_section' can be declared as 'auto *staggered_section' [readability-qualified-auto]

Suggested change
auto staggered_section = options->getSection(section_name + "stag");
auto *staggered_section = options->getSection(section_name + "stag");

Comment thread src/mesh/index_derivs.cxx

for (const auto& [deriv, option_name] : deriv_types) {
auto default_method = DerivativeDefaults::builtinDefaultMethod(deriv);
auto default_name = toString(default_method);

Copy link
Copy Markdown
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 "toString" is directly included [misc-include-cleaner]

      auto default_name = toString(default_method);
                          ^

Comment thread src/mesh/index_derivs.cxx
}

default_method = parseConcreteDiffMethod(default_name);
derivative_defaults.set(direction, deriv, default_method, STAGGER::None);

Copy link
Copy Markdown
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 "STAGGER" is directly included [misc-include-cleaner]

      derivative_defaults.set(direction, deriv, default_method, STAGGER::None);
                                                                ^

Comment thread src/sys/derivs.cxx Outdated
const std::string& UNUSED(method), const std::string& UNUSED(region)) {
Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, const std::string& method,
const std::string& region) {
return DDZ(v, outloc, parseDDZMethodString(method), region);

Copy link
Copy Markdown
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 "(anonymous namespace)::parseDDZMethodString" is directly included [misc-include-cleaner]

  return DDZ(v, outloc, parseDDZMethodString(method), region);
                        ^

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:99: the definition seen here

Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, DIFF_METHOD method,
         ^

include/bout/derivs.hxx:146: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector2D DDZ(const Vector2D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:135: the definition seen here

Vector2D DDZ(const Vector2D& v, CELL_LOC UNUSED(outloc), DIFF_METHOD UNUSED(method),
         ^

include/bout/derivs.hxx:167: differing parameters are named here: ('f'), in definition: ('v')

          ^


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {

const BoutReal sm_p = ma - lhs(ixp);
const BoutReal sm_pp = ma - lhs(ixp2);

BoutReal r = (WENO_SMALL + SQ(sp_c - 2.0 * sp_m + sp_mm))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '-'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

Suggested change
BoutReal r = (WENO_SMALL + SQ(sp_c - 2.0 * sp_m + sp_mm))
BoutReal r = (WENO_SMALL + SQ(sp_c - (2.0 * sp_m) + sp_mm))


// z-component of 1./(C1*D) * Grad_perp(C2)
Field3D coef_z = DDZ(C2coef, location, "FFT") / C1TimesD;
Field3D coef_z = DDZ(C2coef, location, DIFF_C4) / C1TimesD;

Copy link
Copy Markdown
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 "DDZ" is directly included [misc-include-cleaner]

  Field3D coef_z = DDZ(C2coef, location, DIFF_C4) / C1TimesD;
                   ^

for (const auto& ind : coords->dx().getRegion("RGN_ALL")) {
COPY_STRIPE(dx, dy, dz);
COPY_STRIPE(d1_dx, d1_dy, d1_dz);
COPY_STRIPE(IntShiftTorsion);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

    COPY_STRIPE(IntShiftTorsion);
    ^
Additional context

src/mesh/coordinates_accessor.cxx:51: expanded from macro 'COPY_STRIPE'

    MACRO_FOR_EACH(COPY_STRIPE1, __VA_ARGS__) \
                   ^

include/bout/macro_for_each.hxx:99: expanded from macro 'MACRO_FOR_EACH'

                                      _me_1)(mac, __VA_ARGS__))
                                             ^

include/bout/macro_for_each.hxx:19: expanded from macro '_me_1'

#define _me_1(_call, x) _call(x)
                        ^

src/mesh/coordinates_accessor.cxx:44: expanded from macro 'COPY_STRIPE1'

    data[stripe_size * ind.ind + static_cast<int>(Offset::symbol)] = \
         ^

include/bout/macro_for_each.hxx:16: expanded from macro 'BOUT_EXPAND'

#define BOUT_EXPAND(x) x
                       ^


for (const auto& ind : coords->dx().getRegion("RGN_ALL")) {
if (G1.isAllocated()) {
COPY_STRIPE(G1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

      COPY_STRIPE(G1);
      ^
Additional context

src/mesh/coordinates_accessor.cxx:51: expanded from macro 'COPY_STRIPE'

    MACRO_FOR_EACH(COPY_STRIPE1, __VA_ARGS__) \
                   ^

include/bout/macro_for_each.hxx:99: expanded from macro 'MACRO_FOR_EACH'

                                      _me_1)(mac, __VA_ARGS__))
                                             ^

include/bout/macro_for_each.hxx:19: expanded from macro '_me_1'

#define _me_1(_call, x) _call(x)
                        ^

src/mesh/coordinates_accessor.cxx:44: expanded from macro 'COPY_STRIPE1'

    data[stripe_size * ind.ind + static_cast<int>(Offset::symbol)] = \
         ^

include/bout/macro_for_each.hxx:16: expanded from macro 'BOUT_EXPAND'

#define BOUT_EXPAND(x) x
                       ^

COPY_STRIPE(G1);
}
if (G3.isAllocated()) {
COPY_STRIPE(G3);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]

      COPY_STRIPE(G3);
      ^
Additional context

src/mesh/coordinates_accessor.cxx:51: expanded from macro 'COPY_STRIPE'

    MACRO_FOR_EACH(COPY_STRIPE1, __VA_ARGS__) \
                   ^

include/bout/macro_for_each.hxx:99: expanded from macro 'MACRO_FOR_EACH'

                                      _me_1)(mac, __VA_ARGS__))
                                             ^

include/bout/macro_for_each.hxx:19: expanded from macro '_me_1'

#define _me_1(_call, x) _call(x)
                        ^

src/mesh/coordinates_accessor.cxx:44: expanded from macro 'COPY_STRIPE1'

    data[stripe_size * ind.ind + static_cast<int>(Offset::symbol)] = \
         ^

include/bout/macro_for_each.hxx:16: expanded from macro 'BOUT_EXPAND'

#define BOUT_EXPAND(x) x
                       ^

Comment thread src/sys/derivs.cxx
const std::string& UNUSED(method), const std::string& UNUSED(region)) {
Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, const std::string& method,
const std::string& region) {
return DDZ(v, outloc, parseField3DMethodString(method), region);

Copy link
Copy Markdown
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 "(anonymous namespace)::parseField3DMethodString" is directly included [misc-include-cleaner]

  return DDZ(v, outloc, parseField3DMethodString(method), region);
                        ^

DDZ is restored to the previous (eager) implementation that can
dispatch to the FFT method. The new lazy implementation is
`DDZ_stencil` because it is limited to stencil-based methods.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:114: the definition seen here

Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, DIFF_METHOD method,
         ^

include/bout/derivs.hxx:166: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector2D DDZ(const Vector2D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:150: the definition seen here

Vector2D DDZ(const Vector2D& v, CELL_LOC UNUSED(outloc), DIFF_METHOD UNUSED(method),
         ^

include/bout/derivs.hxx:187: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread src/sys/derivs.cxx
const std::string& UNUSED(method), const std::string& UNUSED(region)) {
Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, const std::string& method,
const std::string& region) {
return DDZ(v, outloc, parseField3DMethodString(method), region);

Copy link
Copy Markdown
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 "(anonymous namespace)::parseField3DMethodString" is directly included [misc-include-cleaner]

src/sys/derivs.cxx:40:

- #include <bout/assert.hxx>
+ #include "bout/stencil_expr.hxx"
+ #include <bout/assert.hxx>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread src/invert/laplace/impls/naulin/naulin_laplace.cxx Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

#include <bout/options.hxx>
#include <bout/output.hxx>
#include <bout/scorepwrapper.hxx>
#include <bout/utils.hxx>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: included header scorepwrapper.hxx is not used directly [misc-include-cleaner]

Suggested change
#include <bout/utils.hxx>
#include <bout/utils.hxx>

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:115: the definition seen here

Vector3D DDZ(const Vector3D& v, CELL_LOC outloc, DIFF_METHOD method,
         ^

include/bout/derivs.hxx:166: differing parameters are named here: ('f'), in definition: ('v')

          ^

Comment thread include/bout/derivs.hxx
/// If not given, defaults to DIFF_DEFAULT
/// @param[in] region What region is expected to be calculated
/// If not given, defaults to RGN_NOBNDRY
Vector2D DDZ(const Vector2D& f, CELL_LOC outloc = CELL_DEFAULT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function 'DDZ' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

          ^
Additional context

src/sys/derivs.cxx:151: the definition seen here

Vector2D DDZ(const Vector2D& v, CELL_LOC UNUSED(outloc), DIFF_METHOD UNUSED(method),
         ^

include/bout/derivs.hxx:187: differing parameters are named here: ('f'), in definition: ('v')

          ^

if (coords->symbol().isAllocated()) { \
data[stripe_size * ind.ind + static_cast<int>(Offset::symbol)] = \
coords->symbol()[ind]; \
#define COPY_STRIPE1(symbol) \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: function-like macro 'COPY_STRIPE1' used; consider a 'constexpr' template function [cppcoreguidelines-macro-usage]

#define COPY_STRIPE1(symbol)                                           \
        ^

Ensure that regions are propagated through index derivatives, and
ensure that Bxy has yup/down slices before trying to access them.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

@@ -85,7 +85,9 @@ T flowDerivative(const T& vel, const T& f, CELL_LOC outloc, const std::string& m
const int nPoint = localmesh->getNpoints(direction);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

  const int nPoint = localmesh->getNpoints(direction);
                              ^
Additional context

include/bout/boundary_region.hxx:9: forward declaration of 'Mesh'

class Mesh;
      ^

@@ -146,7 +149,9 @@ T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method,
const int nPoint = localmesh->getNpoints(direction);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: member access into incomplete type 'Mesh' [clang-diagnostic-error]

  const int nPoint = localmesh->getNpoints(direction);
                              ^
Additional context

include/bout/boundary_region.hxx:9: forward declaration of 'Mesh'

class Mesh;
      ^

Requires yup/ydown fields so that the to/fromFieldAligned
transformations are not needed.
Alternative that takes Field3D and checks hasParallelSlices().
Issue arises because only one guard cell is set in toField.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {


template <typename LView, typename RView>
BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& lhs,
const RView&) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: all parameters should be named in a function [readability-named-parameter]

Suggested change
const RView&) const {
const RView& /*unused*/) const {

"boundaries before calling DDY_stencil.");
}

ASSERT1(f.getDirectionY() == YDirectionType::Standard);

Copy link
Copy Markdown
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 "ASSERT1" is directly included [misc-include-cleaner]

  ASSERT1(f.getDirectionY() == YDirectionType::Standard);
  ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GPU work in progress Not ready for merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants