-
Notifications
You must be signed in to change notification settings - Fork 104
Automatically select apropriate parallel slice #3094
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: fci-auto-with-debug-higher-order
Are you sure you want to change the base?
Changes from all commits
d26b825
b27d19d
aaf102d
feec777
49bae21
247c2fb
6e834db
242b9b2
53c9e31
fe888ae
76dc241
eeb7c14
980f00b
fa1bcb4
79e2579
b714f7a
742e6d0
58caf56
6f8a4c9
159c26e
9496211
9b052eb
085948c
288eb77
f3fd242
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 |
|---|---|---|
|
|
@@ -67,7 +67,7 @@ public: | |
| Field2D(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, | ||
| DirectionTypes directions_in = {YDirectionType::Standard, | ||
| ZDirectionType::Average}, | ||
| std::optional<size_t> region = {}); | ||
| std::optional<size_t> region = {}, int yoffset = 0); | ||
|
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/field2d.hxx:26: - class Field2D;
+ #include <optional>
+ class Field2D; |
||
|
|
||
| /*! | ||
| * Copy constructor. After this both fields | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,7 @@ class Field3D; | |||||
| #include "bout/array.hxx" | ||||||
| #include "bout/assert.hxx" | ||||||
| #include "bout/bout_types.hxx" | ||||||
| #include "bout/boutexception.hxx" | ||||||
| #include "bout/field.hxx" | ||||||
|
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: included header boutexception.hxx is not used directly [misc-include-cleaner]
Suggested change
|
||||||
| #include "bout/field2d.hxx" | ||||||
| #include "bout/fieldperp.hxx" | ||||||
|
|
@@ -167,7 +168,7 @@ public: | |||||
| Field3D(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, | ||||||
| DirectionTypes directions_in = {YDirectionType::Standard, | ||||||
| ZDirectionType::Standard}, | ||||||
| std::optional<size_t> regionID = {}); | ||||||
| std::optional<size_t> regionID = {}, int yoffset = 0); | ||||||
|
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 "size_t" is directly included [misc-include-cleaner] include/bout/field3d.hxx:22: - class Field3D;
+ #include <cstddef>
+ class Field3D; |
||||||
|
|
||||||
| /*! | ||||||
| * Copy constructor | ||||||
|
|
@@ -271,23 +272,27 @@ public: | |||||
| /// Return reference to yup field | ||||||
| Field3D& yup(std::vector<Field3D>::size_type index = 0) { | ||||||
| ASSERT2(index < yup_fields.size()); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ASSERT2(yup_fields[index].yoffset == static_cast<int>(index) + 1); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return yup_fields[index]; | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| /// Return const reference to yup field | ||||||
| const Field3D& yup(std::vector<Field3D>::size_type index = 0) const { | ||||||
| ASSERT2(index < yup_fields.size()); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ASSERT2(yup_fields[index].yoffset == static_cast<int>(index) + 1); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return yup_fields[index]; | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
|
|
||||||
| /// Return reference to ydown field | ||||||
| Field3D& ydown(std::vector<Field3D>::size_type index = 0) { | ||||||
| ASSERT2(index < ydown_fields.size()); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ASSERT2(ydown_fields[index].yoffset == -1 - static_cast<int>(index)); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return ydown_fields[index]; | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
|
|
||||||
| /// Return const reference to ydown field | ||||||
| const Field3D& ydown(std::vector<Field3D>::size_type index = 0) const { | ||||||
| ASSERT2(index < ydown_fields.size()); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ASSERT2(ydown_fields[index].yoffset == -1 - static_cast<int>(index)); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return ydown_fields[index]; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -339,6 +344,8 @@ public: | |||||
| void setRegion(std::optional<size_t> id) override; | ||||||
| std::optional<size_t> getRegionID() const override { return regionID; }; | ||||||
|
|
||||||
| int getYoffset() const override { return yoffset; }; | ||||||
|
|
||||||
| /// Return a Region<Ind2D> reference to use to iterate over the x- and | ||||||
| /// y-indices of this field | ||||||
| const Region<Ind2D>& getRegion2D(REGION region) const; | ||||||
|
|
@@ -351,8 +358,27 @@ public: | |||||
| return std::end(getRegion("RGN_ALL")); | ||||||
| }; | ||||||
|
|
||||||
| BoutReal& operator[](const Ind3D& d) { return data[d.ind]; } | ||||||
| const BoutReal& operator[](const Ind3D& d) const { return data[d.ind]; } | ||||||
| BoutReal& operator[](const Ind3D& d) { | ||||||
|
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. It has been a long time since I've looked at this code but could this be
Contributor
Author
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.
The issue is that both the main field, which contains parallel fields, as well as the parallel fields, are of type We could (together with PR #3149) only enable this for Field3DParallel. There might be subtle bugs, where it depends on the type (Field3DParallel/Field3D) on whether it uses the correct indexing. But we could add those with higher CHECK level, so that should be fine. |
||||||
| if (d.yoffset != 0) { | ||||||
| if (yoffset == 0) { | ||||||
| if (hasParallelSlices()) { | ||||||
| return ynext(d.yoffset)[d]; | ||||||
| } | ||||||
| #if CHECK >= 2 | ||||||
| if (isFci()) { // We probably should assert here that this is field aligned | ||||||
|
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. Could this be
Contributor
Author
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. I think it would still need to be guarded - because for FA there are no parallel slices, and thus we need to use the return at the end of the function. |
||||||
| throw BoutException( | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| "Tried to access parallel slices, but they are not calculated!"); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| #endif | ||||||
| } else { | ||||||
| ASSERT2(d.yoffset == yoffset); | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| } | ||||||
| return data[d.ind]; | ||||||
ZedThree marked this conversation as resolved.
Show resolved
Hide resolved
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| const BoutReal& operator[](const Ind3D& d) const { | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| return (*const_cast<Field3D*>(this))[d]; | ||||||
|
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: do not use const_cast to remove const qualifier [cppcoreguidelines-pro-type-const-cast] return (*const_cast<Field3D*>(this))[d];
^ |
||||||
| } | ||||||
|
|
||||||
| BoutReal& operator()(const IndPerp& d, int jy); | ||||||
| const BoutReal& operator()(const IndPerp& d, int jy) const; | ||||||
|
|
@@ -547,6 +573,10 @@ private: | |||||
| template <class T> | ||||||
| Options* track(const T& change, std::string operation); | ||||||
| Options* track(const BoutReal& change, std::string operation); | ||||||
|
|
||||||
| public: | ||||||
dschwoerer marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| int yoffset{0}; | ||||||
|
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: member variable 'yoffset' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes] int yoffset{0};
^ |
||||||
| void setParallelRegions(); | ||||||
| }; | ||||||
|
|
||||||
| // Non-member overloaded operators | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ public: | |
| int yindex_in = -1, | ||
| DirectionTypes directions_in = {YDirectionType::Standard, | ||
| ZDirectionType::Standard}, | ||
| std::optional<size_t> regionID = {}); | ||
| std::optional<size_t> regionID = {}, int yoffset = 0); | ||
|
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 "size_t" is directly included [misc-include-cleaner] include/bout/fieldperp.hxx:25: - class FieldPerp;
+ #include <cstddef>
+ class FieldPerp;
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/fieldperp.hxx:25: - class FieldPerp;
+ #include <optional>
+ class FieldPerp; |
||
|
|
||
| /*! | ||
| * Copy constructor. After this the data | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -168,9 +168,12 @@ template <IND_TYPE N> | |||||
| struct SpecificInd { | ||||||
| int ind = -1; ///< 1D index into Field | ||||||
| int ny = -1, nz = -1; ///< Sizes of y and z dimensions | ||||||
| int yoffset = 0; | ||||||
|
|
||||||
| SpecificInd() = default; | ||||||
| SpecificInd(int i, int ny, int nz) : ind(i), ny(ny), nz(nz){}; | ||||||
| SpecificInd(int i, int ny, int nz, int yoffset) | ||||||
| : ind(i), ny(ny), nz(nz), yoffset(yoffset){}; | ||||||
| explicit SpecificInd(int i) : ind(i){}; | ||||||
|
|
||||||
| /// Allow explicit conversion to an int | ||||||
|
|
@@ -275,7 +278,9 @@ struct SpecificInd { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| inline SpecificInd xp(int dx = 1) const { return {ind + (dx * ny * nz), ny, nz}; } | ||||||
| inline SpecificInd xp(int dx = 1) const { | ||||||
|
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: function 'xp' has inline specifier but is implicitly inlined [readability-redundant-inline-specifier]
Suggested change
|
||||||
| return {ind + (dx * ny * nz), ny, nz, yoffset}; | ||||||
| } | ||||||
| /// The index one point -1 in x | ||||||
| inline SpecificInd xm(int dx = 1) const { return xp(-dx); } | ||||||
| /// The index one point +1 in y | ||||||
|
|
@@ -286,8 +291,18 @@ struct SpecificInd { | |||||
| } | ||||||
| #endif | ||||||
| ASSERT3(std::abs(dy) < ny); | ||||||
| return {ind + (dy * nz), ny, nz}; | ||||||
| return {ind + (dy * nz), ny, nz, yoffset + dy}; | ||||||
| } | ||||||
| inline SpecificInd yp_no_parallel_shift(int dy = 1) const { | ||||||
|
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: function 'yp_no_parallel_shift' has inline specifier but is implicitly inlined [readability-redundant-inline-specifier]
Suggested change
|
||||||
| #if CHECK >= 4 | ||||||
| if (y() + dy < 0 or y() + dy >= ny) { | ||||||
| throw BoutException("Offset in y ({:d}) would go out of bounds at {:d}", dy, ind); | ||||||
| } | ||||||
| #endif | ||||||
| ASSERT3(std::abs(dy) < ny); | ||||||
| return {ind + (dy * nz), ny, nz, yoffset}; | ||||||
| } | ||||||
|
|
||||||
| /// The index one point -1 in y | ||||||
| inline SpecificInd ym(int dy = 1) const { return yp(-dy); } | ||||||
| /// The index one point +1 in z. Wraps around zend to zstart | ||||||
|
|
@@ -297,7 +312,7 @@ struct SpecificInd { | |||||
| inline SpecificInd zp(int dz = 1) const { | ||||||
| ASSERT3(dz >= 0); | ||||||
| dz = dz <= nz ? dz : dz % nz; //Fix in case dz > nz, if not force it to be in range | ||||||
| return {(ind + dz) % nz < dz ? ind - nz + dz : ind + dz, ny, nz}; | ||||||
| return {(ind + dz) % nz < dz ? ind - nz + dz : ind + dz, ny, nz, yoffset}; | ||||||
| } | ||||||
| /// The index one point -1 in z. Wraps around zstart to zend | ||||||
| /// An alternative, non-branching calculation is : | ||||||
|
|
@@ -306,7 +321,7 @@ struct SpecificInd { | |||||
| inline SpecificInd zm(int dz = 1) const { | ||||||
| dz = dz <= nz ? dz : dz % nz; //Fix in case dz > nz, if not force it to be in range | ||||||
| ASSERT3(dz >= 0); | ||||||
| return {(ind) % nz < dz ? ind + nz - dz : ind - dz, ny, nz}; | ||||||
| return {(ind) % nz < dz ? ind + nz - dz : ind - dz, ny, nz, yoffset}; | ||||||
| } | ||||||
| /// Automatically select zm or zp depending on sign | ||||||
| inline SpecificInd zpm(int dz) const { return dz > 0 ? zp(dz) : zm(-dz); } | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,7 +49,7 @@ | |
| #include <bout/assert.hxx> | ||
|
|
||
| Field2D::Field2D(Mesh* localmesh, CELL_LOC location_in, DirectionTypes directions_in, | ||
| std::optional<size_t> UNUSED(regionID)) | ||
| std::optional<size_t> UNUSED(regionID), int UNUSED(yoffset)) | ||
|
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 "UNUSED" is directly included [misc-include-cleaner] src/field/field2d.cxx:29: - #include <bout/boutcomm.hxx>
+ #include "bout/unused.hxx"
+ #include <bout/boutcomm.hxx>
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 "size_t" is directly included [misc-include-cleaner] src/field/field2d.cxx:47: + #include <cstddef>
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] src/field/field2d.cxx:47: + #include <optional> |
||
| : Field(localmesh, location_in, directions_in) { | ||
|
|
||
| if (fieldmesh) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,8 +49,8 @@ | |
|
|
||
| /// Constructor | ||
| Field3D::Field3D(Mesh* localmesh, CELL_LOC location_in, DirectionTypes directions_in, | ||
| std::optional<size_t> regionID) | ||
| : Field(localmesh, location_in, directions_in), regionID{regionID} { | ||
| std::optional<size_t> regionID, const int yoffset) | ||
|
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 "size_t" is directly included [misc-include-cleaner] src/field/field3d.cxx:33: + #include <cstddef>
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] src/field/field3d.cxx:33: + #include <optional> |
||
| : Field(localmesh, location_in, directions_in), regionID{regionID}, yoffset{yoffset} { | ||
| #if BOUT_USE_TRACK | ||
| name = "<F3D>"; | ||
| #endif | ||
|
|
@@ -66,7 +66,7 @@ Field3D::Field3D(Mesh* localmesh, CELL_LOC location_in, DirectionTypes direction | |
| /// later) | ||
| Field3D::Field3D(const Field3D& f) | ||
| : Field(f), data(f.data), yup_fields(f.yup_fields), ydown_fields(f.ydown_fields), | ||
| regionID(f.regionID) { | ||
| regionID(f.regionID), yoffset(f.yoffset) { | ||
|
|
||
| TRACE("Field3D(Field3D&)"); | ||
|
|
||
|
|
@@ -157,7 +157,9 @@ void Field3D::splitParallelSlices() { | |
| // Note the fields constructed here will be fully overwritten by the | ||
| // ParallelTransform, so we don't need a full constructor | ||
| yup_fields.emplace_back(fieldmesh); | ||
| yup_fields[i].yoffset = i + 1; | ||
| ydown_fields.emplace_back(fieldmesh); | ||
| ydown_fields[i].yoffset = -1 - i; | ||
| if (isFci()) { | ||
| yup_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", i + 1)); | ||
| ydown_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", -i - 1)); | ||
|
|
@@ -224,6 +226,15 @@ bool Field3D::requiresTwistShift(bool twist_shift_enabled) { | |
| getDirectionY()); | ||
| } | ||
|
|
||
| void Field3D::setParallelRegions() { | ||
| for (int i = 0; i < fieldmesh->ystart; ++i) { | ||
| yup_fields[i].yoffset = i + 1; | ||
| yup_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", i + 1)); | ||
| ydown_fields[i].yoffset = -1 - i; | ||
| ydown_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", -1 - i)); | ||
| } | ||
| } | ||
|
|
||
| // Not in header because we need to access fieldmesh | ||
| BoutReal& Field3D::operator()(const IndPerp& d, int jy) { | ||
| return operator[](fieldmesh->indPerpto3D(d, jy)); | ||
|
|
@@ -277,6 +288,7 @@ Field3D& Field3D::operator=(const Field3D& rhs) { | |
| yup_fields = rhs.yup_fields; | ||
| ydown_fields = rhs.ydown_fields; | ||
| regionID = rhs.regionID; | ||
| yoffset = rhs.yoffset; | ||
|
|
||
| // Copy the data and data sizes | ||
| nx = rhs.nx; | ||
|
|
@@ -295,12 +307,13 @@ Field3D& Field3D::operator=(Field3D&& rhs) { | |
| // Move parallel slices or delete existing ones. | ||
| yup_fields = std::move(rhs.yup_fields); | ||
| ydown_fields = std::move(rhs.ydown_fields); | ||
| regionID = rhs.regionID; | ||
| yoffset = rhs.yoffset; | ||
|
|
||
| // Move the data and data sizes | ||
| nx = rhs.nx; | ||
| ny = rhs.ny; | ||
| nz = rhs.nz; | ||
| regionID = rhs.regionID; | ||
|
|
||
| data = std::move(rhs.data); | ||
|
|
||
|
|
@@ -896,6 +909,7 @@ void swap(Field3D& first, Field3D& second) noexcept { | |
| swap(first.deriv, second.deriv); | ||
| swap(first.yup_fields, second.yup_fields); | ||
| swap(first.ydown_fields, second.ydown_fields); | ||
| swap(first.yoffset, second.yoffset); | ||
| } | ||
|
|
||
| const Region<Ind3D>& | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,7 +35,8 @@ | |
| #include <bout/utils.hxx> | ||
|
|
||
| FieldPerp::FieldPerp(Mesh* localmesh, CELL_LOC location_in, int yindex_in, | ||
| DirectionTypes directions, std::optional<size_t> UNUSED(regionID)) | ||
| DirectionTypes directions, std::optional<size_t> UNUSED(regionID), | ||
|
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 "DirectionTypes" is directly included [misc-include-cleaner] DirectionTypes directions, std::optional<size_t> UNUSED(regionID), int UNUSED(yoffset))
^
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 "UNUSED" is directly included [misc-include-cleaner] src/field/fieldperp.cxx:25: - #include <bout/boutcomm.hxx>
+ #include "bout/unused.hxx"
+ #include <bout/boutcomm.hxx>
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 "size_t" is directly included [misc-include-cleaner] src/field/fieldperp.cxx:29: + #include <cstddef>
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] src/field/fieldperp.cxx:29: + #include <optional>
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 "DirectionTypes" is directly included [misc-include-cleaner] DirectionTypes directions, std::optional<size_t> UNUSED(regionID),
^ |
||
| int UNUSED(yoffset)) | ||
| : Field(localmesh, location_in, directions), yindex(yindex_in) { | ||
| if (fieldmesh) { | ||
| nx = fieldmesh->LocalNx; | ||
|
|
||
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.
warning: no header providing "size_t" is directly included [misc-include-cleaner]
include/bout/field2d.hxx:26: