From 3c82775ad189070211594a2404d903e5c41f5aa1 Mon Sep 17 00:00:00 2001 From: lkotipal Date: Tue, 9 Jul 2024 14:23:48 +0300 Subject: [PATCH 1/3] Implement finding neighbors at offset of arbitrary smaller size, in the worst way possible --- dccrg.hpp | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/dccrg.hpp b/dccrg.hpp index 4d9fe0c..3e4d921 100644 --- a/dccrg.hpp +++ b/dccrg.hpp @@ -2961,7 +2961,7 @@ template < for (const auto& neighbor_i: this->neighbors_of.at(cell)) { const auto& offsets = neighbor_i.second; if (offsets[3] <= 1) { - if (offsets[0] == x and offsets[1] == y and offsets[2] == z) { + if (offsets[0] == x && offsets[1] == y && offsets[2] == z) { return_neighbors.push_back(neighbor_i); } } else { @@ -2978,7 +2978,7 @@ template < } scaled_offsets[i] /= scaled_offsets[3]; } - if (scaled_offsets[0] == x and scaled_offsets[1] == y and scaled_offsets[2] == z) { + if (scaled_offsets[0] == x && scaled_offsets[1] == y && scaled_offsets[2] == z) { return_neighbors.push_back(neighbor_i); } } @@ -2987,6 +2987,92 @@ template < return return_neighbors; } + // Doesn't support denominator < 0 + std::vector< + std::pair< + uint64_t, + std::array + > + > get_neighbors_of_at_offset( + const uint64_t cell, + const int x, + const int y, + const int z, + const int denom + ) const { + std::vector>> return_neighbors; + if ( + this->cell_process.count(cell) == 0 || + this->cell_process.at(cell) != this->rank || + (x == 0 and y == 0 and z == 0) || + denom < 0 + ) { + return return_neighbors; + } + + std::vector xyz = {x, y, z}; + for (size_t i = 0; i < 3; i++) { + // round away from zero, stackoverflow.com/a/2745086 + if (std::abs(xyz[i]) <= 1) { + continue; + } + if (xyz[i] > 1) { + xyz[i] += denom - 1; + } else { + xyz[i] -= denom - 1; + } + xyz[i] /= denom; + } + + for (const auto& neighbor_i : this->get_neighbors_of_at_offset(cell, xyz[0], xyz[1], xyz[2])) { + const auto& offsets = neighbor_i.second; + if (offsets[3] == denom) { + if (offsets[0] == x && offsets[1] == y && offsets[2] == z) { + return_neighbors.push_back(neighbor_i); + } + } else if (offsets[3] < denom) { + // If we're looking at cells larger than denom, calculate our desired xyz offset in that size + std::vector xyz = {x, y, z}; + int factor = offsets[3] > 0 ? denom/offsets[3] : -offsets[3] * denom; + for (size_t i = 0; i < 3; i++) { + // round away from zero, stackoverflow.com/a/2745086 + if (std::abs(xyz[i]) <= 1) { + continue; + } + if (xyz[i] > 1) { + xyz[i] += factor - 1; + } else { + xyz[i] -= factor - 1; + } + xyz[i] /= factor; + } + + if (offsets[0] == xyz[0] && offsets[1] == xyz[1] && offsets[2] == xyz[2]) { + return_neighbors.push_back(neighbor_i); + } + } else { // offsets[3] > denom + // If we're looking at cells smaller than denom, calculate their offsets in denom size + auto scaled_offsets = offsets; + for (size_t i = 0; i < 3; i++) { + // round away from zero, stackoverflow.com/a/2745086 + if (std::abs(scaled_offsets[i]) <= 1) { + continue; + } + if (scaled_offsets[i] > 1) { + scaled_offsets[i] += scaled_offsets[3]/denom - 1; + } else { + scaled_offsets[i] -= scaled_offsets[3]/denom - 1; + } + scaled_offsets[i] /= scaled_offsets[3]/denom; + } + if (scaled_offsets[0] == x && scaled_offsets[1] == y && scaled_offsets[2] == z) { + return_neighbors.push_back(neighbor_i); + } + } + } + + return return_neighbors; + } /*! Returns neighbors of given local cell that are on another process. From b534dd3c1967a76a3222be1d94c1f9d805511eab Mon Sep 17 00:00:00 2001 From: lkotipal Date: Thu, 11 Jul 2024 14:56:39 +0300 Subject: [PATCH 2/3] DRY --- dccrg.hpp | 53 +++++++++++++---------------------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/dccrg.hpp b/dccrg.hpp index 3e4d921..7d42119 100644 --- a/dccrg.hpp +++ b/dccrg.hpp @@ -2923,6 +2923,11 @@ template < return this->neighborhood_length; } + // round away from zero, stackoverflow.com/a/2745086 + static int divide_away_from_zero(const int x, const int y) + { + return x > 0 ? (x + y - 1) / y : (x - y + 1) / y; + } /*! Returns all neighbors of given cell that are at given offset from it. @@ -2967,16 +2972,7 @@ template < } else { auto scaled_offsets = offsets; for (size_t i = 0; i < 3; i++) { - if (std::abs(scaled_offsets[i]) <= 1) { - continue; - } - // round away from zero, stackoverflow.com/a/2745086 - if (scaled_offsets[i] > 1) { - scaled_offsets[i] += scaled_offsets[3] - 1; - } else { - scaled_offsets[i] -= scaled_offsets[3] - 1; - } - scaled_offsets[i] /= scaled_offsets[3]; + scaled_offsets[i] = divide_away_from_zero(scaled_offsets[i], scaled_offsets[3]); } if (scaled_offsets[0] == x && scaled_offsets[1] == y && scaled_offsets[2] == z) { return_neighbors.push_back(neighbor_i); @@ -3010,18 +3006,13 @@ template < return return_neighbors; } + if (denom == 1) { + return get_neighbors_of_at_offset(cell, x, y, z); + } + std::vector xyz = {x, y, z}; for (size_t i = 0; i < 3; i++) { - // round away from zero, stackoverflow.com/a/2745086 - if (std::abs(xyz[i]) <= 1) { - continue; - } - if (xyz[i] > 1) { - xyz[i] += denom - 1; - } else { - xyz[i] -= denom - 1; - } - xyz[i] /= denom; + xyz[i] = divide_away_from_zero(xyz[i], denom); } for (const auto& neighbor_i : this->get_neighbors_of_at_offset(cell, xyz[0], xyz[1], xyz[2])) { @@ -3035,16 +3026,7 @@ template < std::vector xyz = {x, y, z}; int factor = offsets[3] > 0 ? denom/offsets[3] : -offsets[3] * denom; for (size_t i = 0; i < 3; i++) { - // round away from zero, stackoverflow.com/a/2745086 - if (std::abs(xyz[i]) <= 1) { - continue; - } - if (xyz[i] > 1) { - xyz[i] += factor - 1; - } else { - xyz[i] -= factor - 1; - } - xyz[i] /= factor; + xyz[i] = divide_away_from_zero(xyz[i], factor); } if (offsets[0] == xyz[0] && offsets[1] == xyz[1] && offsets[2] == xyz[2]) { @@ -3054,16 +3036,7 @@ template < // If we're looking at cells smaller than denom, calculate their offsets in denom size auto scaled_offsets = offsets; for (size_t i = 0; i < 3; i++) { - // round away from zero, stackoverflow.com/a/2745086 - if (std::abs(scaled_offsets[i]) <= 1) { - continue; - } - if (scaled_offsets[i] > 1) { - scaled_offsets[i] += scaled_offsets[3]/denom - 1; - } else { - scaled_offsets[i] -= scaled_offsets[3]/denom - 1; - } - scaled_offsets[i] /= scaled_offsets[3]/denom; + scaled_offsets[i] = divide_away_from_zero(scaled_offsets[i], scaled_offsets[3] / denom); } if (scaled_offsets[0] == x && scaled_offsets[1] == y && scaled_offsets[2] == z) { return_neighbors.push_back(neighbor_i); From 916b97718b6a17056a59a9433b0ea553d43c2d3b Mon Sep 17 00:00:00 2001 From: lkotipal Date: Thu, 11 Jul 2024 15:36:09 +0300 Subject: [PATCH 3/3] Control flow adjustment --- dccrg.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dccrg.hpp b/dccrg.hpp index 7d42119..57b7454 100644 --- a/dccrg.hpp +++ b/dccrg.hpp @@ -2996,6 +2996,10 @@ template < const int z, const int denom ) const { + if (denom == 1) { + return get_neighbors_of_at_offset(cell, x, y, z); + } + std::vector>> return_neighbors; if ( this->cell_process.count(cell) == 0 || @@ -3006,10 +3010,6 @@ template < return return_neighbors; } - if (denom == 1) { - return get_neighbors_of_at_offset(cell, x, y, z); - } - std::vector xyz = {x, y, z}; for (size_t i = 0; i < 3; i++) { xyz[i] = divide_away_from_zero(xyz[i], denom); @@ -3023,7 +3023,7 @@ template < } } else if (offsets[3] < denom) { // If we're looking at cells larger than denom, calculate our desired xyz offset in that size - std::vector xyz = {x, y, z}; + xyz = {x, y, z}; int factor = offsets[3] > 0 ? denom/offsets[3] : -offsets[3] * denom; for (size_t i = 0; i < 3; i++) { xyz[i] = divide_away_from_zero(xyz[i], factor);