Improvements for hermitespline interpolation#3298
Conversation
For FCI we need to be able to access "random" data from the adjacent slices. If they are split in x-direction, this requires some tricky communication pattern. It can be used like this: ``` // Create object GlobalField3DAccess fci_comm(thismesh); // let it know what data points will be required: // where IndG3D is an index in the global field, which would be the // normal Ind3D if there would be only one proc. fci_comm.get(IndG3D(i, ny, nz)); // If all index have been added, the communication pattern will be // established. This has to be called by all processors in parallel fci_comm.setup() // Once the data for a given field is needed, it needs to be // communicated: GlobalField3DAccessInstance global_data = fci_comm.communicate(f3d); // and can be accessed like this BoutReal data = global_data[IndG3D(i, ny, nz)]; // ny and nz in the IndG3D are always optional. ```
If they are two instances of the same template, this allows to have an if in the inner loop that can be optimised out.
lower_bound takes into account the data is sorted
Ensures we all ways check for monotonicity
Tags were different for sender and receiver
Otherwise mpi might wait for the wrong request.
to avoid confusion whether the offsets are for sending or receiving
Using a local set for each thread ensures we do not need a mutex for adding data, at the cost of having to merge the different sets later.
We want to skip sending if there is no data for this process ...
The result needs to be well understood, as the indices are a mix of local and global indices, as we need to access non-local data.
| /// Perhaps should only impose near boundaries, since that is where | ||
| /// problems most obviously occur. | ||
| template <bool monotonic> | ||
| class XZHermiteSplineBase : public XZInterpolation { |
There was a problem hiding this comment.
warning: class 'XZHermiteSplineBase' defines a non-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 XZHermiteSplineBase : public XZInterpolation {
^| Tensor<SpecificInd<IND_TYPE::IND_3D>> i_corner; // index of bottom-left grid point | ||
| Tensor<int> k_corner; // z-index of bottom-left grid point | ||
|
|
||
| std::unique_ptr<GlobalField3DAccess> gf3daccess; |
There was a problem hiding this comment.
warning: member variable 'gf3daccess' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]
std::unique_ptr<GlobalField3DAccess> gf3daccess;
^| Tensor<int> k_corner; // z-index of bottom-left grid point | ||
|
|
||
| std::unique_ptr<GlobalField3DAccess> gf3daccess; | ||
| Tensor<std::array<int, 4>> g3dinds; |
There was a problem hiding this comment.
warning: member variable 'g3dinds' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]
Tensor<std::array<int, 4>> g3dinds;
^| #endif | ||
|
|
||
| /// Factors to allow for some wiggleroom | ||
| BoutReal abs_fac_monotonic{1e-2}; |
There was a problem hiding this comment.
warning: member variable 'abs_fac_monotonic' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]
BoutReal abs_fac_monotonic{1e-2};
^
src/mesh/parallel/fci_comm.hxx
Outdated
| int ind; | ||
| }; | ||
| struct globalToLocal1D { | ||
| const int mg; |
There was a problem hiding this comment.
warning: member 'mg' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]
const int mg;
^|
|
||
| #if USE_NEW_WEIGHTS | ||
| #ifdef HS_USE_PETSC | ||
| std::unique_ptr<GlobalField3DAccessInstance> gf; |
There was a problem hiding this comment.
warning: no header providing "std::unique_ptr" is directly included [misc-include-cleaner]
src/mesh/interpolation/hermite_spline_xz.cxx:30:
- #include <string>
+ #include <memory>
+ #include <string>|
|
||
| #if USE_NEW_WEIGHTS | ||
| #ifdef HS_USE_PETSC | ||
| std::unique_ptr<GlobalField3DAccessInstance> gf; |
There was a problem hiding this comment.
warning: variable 'gf' of type 'std::unique_ptr' can be declared 'const' [misc-const-correctness]
| std::unique_ptr<GlobalField3DAccessInstance> gf; | |
| std::unique_ptr<GlobalField3DAccessInstance> const gf; |
|
|
||
| if constexpr (monotonic) { | ||
| #endif | ||
| const auto corners = {(*gf)[IndG3D(g3dinds[i][0])], (*gf)[IndG3D(g3dinds[i][1])], |
There was a problem hiding this comment.
warning: no header providing "IndG3D" is directly included [misc-include-cleaner]
const auto corners = {(*gf)[IndG3D(g3dinds[i][0])], (*gf)[IndG3D(g3dinds[i][1])],
^| f_interp[iyp] = std::min(f_interp[iyp], minmax.second + diff); | ||
| } | ||
| #if USE_NEW_WEIGHTS and defined(HS_USE_PETSC) | ||
| ASSERT2(std::isfinite(cptr[int(i)])); |
There was a problem hiding this comment.
warning: no header providing "std::isfinite" is directly included [misc-include-cleaner]
ASSERT2(std::isfinite(cptr[int(i)]));
^| // NOLINTEND(cppcoreguidelines-macro-usage,bugprone-macro-parentheses) | ||
|
|
||
| enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2 }; | ||
| enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2, IND_GLOBAL_3D = 3 }; |
There was a problem hiding this comment.
warning: enum 'IND_TYPE' uses a larger base type ('int', size: 4 bytes) than necessary for its value set, consider using 'std::uint8_t' (1 byte) as the base type to reduce its size [performance-enum-size]
enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2, IND_GLOBAL_3D = 3 };
^| }; | ||
|
|
||
| XZHermiteSpline::XZHermiteSpline(int y_offset, Mesh* meshin) | ||
| template <bool monotonic> |
There was a problem hiding this comment.
warning: constructor does not initialize these fields: petscWeights, rhs, result [cppcoreguidelines-pro-type-member-init]
include/bout/interpolation_xz.hxx:179:
- Mat petscWeights;
- Vec rhs, result;
+ Mat petscWeights{};
+ Vec rhs{}, result{};| } | ||
| o_ids.clear(); | ||
| #endif | ||
| toGet.resize(static_cast<size_t>(g2lx.npe * g2ly.npe * g2lz.npe)); |
There was a problem hiding this comment.
warning: either cast from 'int' to 'size_t' (aka 'unsigned long') is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
toGet.resize(static_cast<size_t>(g2lx.npe * g2ly.npe * g2lz.npe));
^| int offset = 0; | ||
| for (const auto& get : toGet) { | ||
| getOffsets.push_back(offset); | ||
| offset += get.size(); |
There was a problem hiding this comment.
warning: narrowing conversion from 'size_type' (aka 'unsigned long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]
offset += get.size();
^| auto it = std::lower_bound(vec.begin(), vec.end(), tofind); | ||
| ASSERT3(it != vec.end()); | ||
| ASSERT3(*it == tofind); | ||
| mapping[id] = std::distance(vec.begin(), it) + getOffsets[proc]; |
There was a problem hiding this comment.
warning: narrowing conversion from 'typename iterator_traits<__gnu_cxx::__normal_iterator<const int *, std::vector<int, std::allocator>>>::difference_type' (aka 'long') to signed type 'mapped_type' (aka 'int') is implementation-defined [bugprone-narrowing-conversions]
mapping[id] = std::distance(vec.begin(), it) + getOffsets[proc];
^|
|
||
| public: | ||
| const fci_comm::XYZ2Ind<Ind3D> xyzl; | ||
| const fci_comm::XYZ2Ind<IndG3D> xyzg; |
There was a problem hiding this comment.
warning: member variable 'xyzg' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes]
const fci_comm::XYZ2Ind<IndG3D> xyzg;
^| } | ||
| auto ret = | ||
| MPI_Irecv(static_cast<void*>(data.data() + getOffsets[proc]), | ||
| toGet[proc].size(), MPI_DOUBLE, proc, 666, comm, reqs.data() + cnt1); |
There was a problem hiding this comment.
warning: narrowing conversion from 'size_t' (aka 'unsigned long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]
toGet[proc].size(), MPI_DOUBLE, proc, 666, comm, reqs.data() + cnt1);
^| } | ||
| auto ret = | ||
| MPI_Irecv(static_cast<void*>(data.data() + getOffsets[proc]), | ||
| toGet[proc].size(), MPI_DOUBLE, proc, 666, comm, reqs.data() + cnt1); |
There was a problem hiding this comment.
warning: narrowing conversion from 'size_type' (aka 'unsigned long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]
toGet[proc].size(), MPI_DOUBLE, proc, 666, comm, reqs.data() + cnt1);
^| for (auto i : toSend[proc]) { | ||
| sendBuffer[cnt++] = f[Ind3D(i)]; | ||
| } | ||
| auto ret = MPI_Send(start, toSend[proc].size(), MPI_DOUBLE, proc, 666, comm); |
There was a problem hiding this comment.
warning: narrowing conversion from 'size_t' (aka 'unsigned long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]
auto ret = MPI_Send(start, toSend[proc].size(), MPI_DOUBLE, proc, 666, comm);
^| for (auto i : toSend[proc]) { | ||
| sendBuffer[cnt++] = f[Ind3D(i)]; | ||
| } | ||
| auto ret = MPI_Send(start, toSend[proc].size(), MPI_DOUBLE, proc, 666, comm); |
There was a problem hiding this comment.
warning: narrowing conversion from 'size_type' (aka 'unsigned long') to signed type 'int' is implementation-defined [bugprone-narrowing-conversions]
auto ret = MPI_Send(start, toSend[proc].size(), MPI_DOUBLE, proc, 666, comm);
^
Includes X-splitting also for monotonichermitespline and more.