Conversation
b12e871 to
090441d
Compare
67e6434 to
bb07d04
Compare
joewallwork
left a comment
There was a problem hiding this comment.
Thanks for this @TomMelt. Here's some initial feedback. I haven't checked all of the logic but let me know if there's anything in particular you want checking.
| @@ -52,11 +54,36 @@ class Halo { | |||
|
|
|||
| /*! | |||
| * @brief Constructs a halo object from DGVector | |||
There was a problem hiding this comment.
| * @brief Constructs a halo object from DGVector | |
| * @brief Constructs a halo object from DGVectorHolder |
| template <int N> Halo(DGVectorHolder<N>& dgvh) | ||
| { | ||
| m_numComps = N; | ||
| setSpatialDims(); | ||
| intializeHaloMetadata(); | ||
| } | ||
|
|
||
| /*! | ||
| * @brief Constructs a halo object from DGVector | ||
| * @param dgv DGVector object to create halo from | ||
| */ | ||
| template <int N> Halo(DGVector<N>& dgv) | ||
| { | ||
| m_numComps = N; | ||
| isVertex = false; | ||
| setSpatialDims(); | ||
| intializeHaloMetadata(); | ||
| } | ||
|
|
||
| /*! | ||
| * @brief Constructs a halo object from CGVector | ||
| * @param cgv CGVector object to create halo from | ||
| */ | ||
| template <int N> Halo(CGVector<N>& cgv) | ||
| { | ||
| m_numComps = 1; | ||
| isCG = true; | ||
| CGdegree = N; | ||
| nCells = CGdegree; | ||
| setSpatialDims(); | ||
| intializeHaloMetadata(); |
There was a problem hiding this comment.
In none of these cases do the constructors depend on their argument, right? The only information that's being used is the value of N and the type. So do we actually need to provide dgv, dgvh, or cgv as arguments?
There was a problem hiding this comment.
There seems to be quite a lot of implementation in this header file. Might it be better to separate it out into core/src/Halo.cpp?
There was a problem hiding this comment.
Agreed. Function definitions should go in a source file if possible. Exceptions are (public) template functions which have to be defined in the header and maybe one-liners.
| for (size_t comp = 0; comp < m_numComps; ++comp) { | ||
| Eigen::Map<Eigen::ArrayXXd, 0, Eigen::InnerStride<Eigen::Dynamic>> source_map( | ||
| source.col(comp).data(), m_Nx, m_Ny, Eigen::InnerStride<>(m_numComps)); | ||
| Eigen::Map<Eigen::ArrayXXd> buffer_map(send[comp].data(), buffer_len, nCells); | ||
| for (auto edge : edges) { |
There was a problem hiding this comment.
This code could benefit from some comments as I'm struggling to understand what it does. numComps is the N value in the template constructor, right?
| /** | ||
| * @brief Calculate which edge the send position sendPos would fall under in the send buffer | ||
| * | ||
| */ | ||
| Edge edgeFromSendPos(int sendPos, int fromRank) |
There was a problem hiding this comment.
Missing @params etc in docstring
| count = 1; | ||
| disp = disp + sendEdge; | ||
| recvOffset = recvOffset + 4; | ||
| // this is messy |
There was a problem hiding this comment.
Is this a TODO to do it differently?
| if (metadata.cornerRanks[corner].size() > 0) { | ||
| // non-periodic case | ||
| hasCorner = true; | ||
| isPeriodic = false; | ||
| } else if (metadata.cornerRanksPeriodic[corner].size() > 0) { | ||
| // periodic case | ||
| hasCorner = true; | ||
| isPeriodic = true; | ||
| } |
There was a problem hiding this comment.
Presumably it's impossible for both conditions to be true at the same time? Or would it be useful to include a failure mode in case it happens due to a bug?
| } | ||
| } | ||
|
|
||
| template <typename T> void populateTarget(T& target) |
There was a problem hiding this comment.
Please add a docstring.
|
|
||
| readNeighbourData(ncFile); | ||
|
|
||
| // cornerHaloRecv doesn't need to be read because it can be easily calculated. |
There was a problem hiding this comment.
I guess there's an assumption (probably right) that a small amount of computation is cheaper than a small amount of I/O?
There was a problem hiding this comment.
Nice to reduce the amount of numbers hard-coded in code here, well done!
| neighbourArray neighbourHaloSendPeriodic; | ||
| neighbourArray neighbourHaloRecvPeriodic; | ||
|
|
||
| typedef std::array<std::vector<int>, N_CORNER> cornerArray; |
There was a problem hiding this comment.
Types should be in CamelCase.
using CornerArray = std::array<std::vector<int>, N_CORNER>;
| std::array<std::string, N_CORNER> cornerNames | ||
| = { "top_left", "top_right", "bottom_right", "bottom_left" }; | ||
|
|
||
| typedef std::array<std::vector<int>, N_EDGE> neighbourArray; |
There was a problem hiding this comment.
Types should be in CamelCase. Prefer using over typedef (see CppCoreGuidlines).
using NeighbourArray = std::array<std::vector<int>, N_EDGE>;
| * @brief Gets the extents of the grid in the X direction for all ranks. | ||
| * @return A vector containing the number of grid points in X for each rank. | ||
| */ | ||
| std::vector<int> getRankExtentsX() const; |
There was a problem hiding this comment.
Return by const& to prevent unnecessary copies.
| * @brief Gets the extents of the grid in the Y direction for all ranks. | ||
| * @return A vector containing the number of grid points in Y for each rank. | ||
| */ | ||
| std::vector<int> getRankExtentsY() const; |
There was a problem hiding this comment.
Return by const& to prevent unnecessary copies.
| int fromRank; | ||
| size_t disp; |
There was a problem hiding this comment.
These variables could be defined closer to where they are used, i.e. in the if (hasCorner) branch.
| auto buffer_len = recvBufferSize / CGdegree; | ||
| for (size_t comp = 0; comp < m_numComps; ++comp) { | ||
| Eigen::Map<Eigen::ArrayXXd> rmap(recv[comp].data(), buffer_len, nCells); | ||
| auto offset = buffer_len - (4 - corner) * nCells; |
There was a problem hiding this comment.
Where does this 4 come from? Is it just Corner::N_CORNER?
| std::vector<int> ModelMetadata::getRankExtentsX() const { return rankExtentsX; } | ||
| std::vector<int> ModelMetadata::getRankExtentsY() const { return rankExtentsY; } |
There was a problem hiding this comment.
| std::vector<int> ModelMetadata::getRankExtentsX() const { return rankExtentsX; } | |
| std::vector<int> ModelMetadata::getRankExtentsY() const { return rankExtentsY; } | |
| const std::vector<int>& ModelMetadata::getRankExtentsX() const { return rankExtentsX; } | |
| const std::vector<int>& ModelMetadata::getRankExtentsY() const { return rankExtentsY; } |
| constexpr ModelMetadata::Corner TOP_LEFT = ModelMetadata::Corner::TOP_LEFT; | ||
| constexpr ModelMetadata::Corner TOP_RIGHT = ModelMetadata::Corner::TOP_RIGHT; | ||
| constexpr ModelMetadata::Corner BOTTOM_RIGHT = ModelMetadata::Corner::BOTTOM_RIGHT; | ||
| constexpr ModelMetadata::Corner BOTTOM_LEFT = ModelMetadata::Corner::BOTTOM_LEFT; |
There was a problem hiding this comment.
If the intend here is just to introduce shorter names, using would be more clear:
using enum ModelMetadata::Corner;
| auto extentX = metadata.getRankExtentsX()[fromRank]; | ||
| auto extentY = metadata.getRankExtentsY()[fromRank]; |
There was a problem hiding this comment.
I think it would be better to not use auto if the expression has a simple type. Here the type is just int while in many other places the standard size type size_t is used instead. The distinction between signed and unsigned ints is important because the following conditions would not work with an unsigned type.
| // TODO this is too big. Should only be 2 x CGdegree * haloWidth (extentX + extentY) | ||
| auto fromRankSendBufferSize = 2 * haloWidth * CGdegree * (extentX + extentY); |
There was a problem hiding this comment.
Is this todo outdated? The line below looks just like suggested.
Add corner neighbours into halo exchange logic
Task List
Change Description
This PR has the following key changes:
CGVectorandDGVectorHolderexchange (this is required for corners and edges)Test Description
HaloExchangePB_test.cppHaloExchangeCB_test.cppcreates test data for all the array types:HFieldVertexFieldDGFieldDGVectorCGVectorI modified the previous version, so that the model data are created in such a way that the value of each cell can be calculated based on its indices. Therefore we can check after exchange that all of the cells have been exchanged successfully. This also now allows us to change the number of ranks arbitrarily (assuming you also provide the appropriate
partition_metadatafile.ModelMetadataCB_test.cppandModelMetadataPB_test.cppSmall modifications have been made to the periodic and closed boundary
ModelMetadatatests.The changes now add the additional corner neighbour metadata and check that it is ready correctly.
partition_metadata_3_cb.cdlandpartition_metadata_3_pb.cdlThese files are now generated at compile time by running the
decomptool on a new filehalo_test_mask.cdl. This is in line with similar changes introduced by @joewallwork on the XIOS tests.Other Details
domain_decopgit commit has now been bumped to the latest version on main. This version of the decomp tool contains the corner neighbour metadata.Further work