From 592f59dbc5dc2de9a3c3fd2bd9db5bc2a1680cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20L=C3=BCbke?= Date: Thu, 8 Sep 2022 12:46:26 +0200 Subject: [PATCH] perf: represent inner boundary conditions with a std::map refactor: inner boundary conditions are now accessible via methods test: update test cases --- include/BoundaryCondition.hpp | 40 ++++++++++++------ src/BoundaryCondition.cpp | 74 +++++++++++++++++++++++++++++----- test/testBoundaryCondition.cpp | 50 +++++++++++++++-------- test/testDiffusion.cpp | 2 +- 4 files changed, 126 insertions(+), 40 deletions(-) diff --git a/include/BoundaryCondition.hpp b/include/BoundaryCondition.hpp index 6dc8dae..a31387d 100644 --- a/include/BoundaryCondition.hpp +++ b/include/BoundaryCondition.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -128,6 +129,31 @@ public: */ auto col_boundary(uint32_t i) const -> bc_tuple; + /** + * Sets one cell of the inner grid to a given boundary condition. + * + * \param bc Boundary condition to be set. + * \param x Index of grid cell in x direction. + * \param y Index of grid cell in y direction. + */ + void setInnerBC(boundary_condition bc, int x, int y); + + /** + * Unsets a previously set inner boundary condition. + * + * \param x Index of grid cell in x direction. + * \param y Index of grid cell in y direction. + */ + void unsetInnerBC(int x, int y); + + /** + * Returns the current boundary condition set for specific inner grid cell. + * + * \param x Index of grid cell in x direction. + * \param y Index of grid cell in y direction. + */ + auto getInnerBC(int x, int y) -> boundary_condition; + /** * Get a row of field and its inner boundary conditions. * @@ -162,7 +188,7 @@ public: private: std::vector bc_internal; - bc_vec special_cells; + std::map inner_cells; uint8_t dim; @@ -200,12 +226,6 @@ public: * \returns Boundary condition */ boundary_condition operator()(uint8_t side, uint32_t i) const { - if (side == BC_INNER) { - if (i > maxindex) { - throw std::out_of_range("Index exceeds grid cell numbers"); - } - return special_cells[i]; - } if (dim != 2) { throw std::invalid_argument( "Only 2D grids support 2 parameters in operator"); @@ -243,12 +263,6 @@ public: * \returns Boundary condition */ boundary_condition &operator()(uint8_t side, uint32_t i) { - if (side == BC_INNER) { - if (i > maxindex) { - throw std::out_of_range("Index exceeds grid cell numbers"); - } - return special_cells[i]; - } if (dim != 2) { throw std::invalid_argument("Explicit setting of bc value with 2 " "parameters is only supported for 2D grids"); diff --git a/src/BoundaryCondition.cpp b/src/BoundaryCondition.cpp index ba2e403..51065e1 100644 --- a/src/BoundaryCondition.cpp +++ b/src/BoundaryCondition.cpp @@ -10,7 +10,6 @@ constexpr uint8_t DIM_2D = 4; tug::bc::BoundaryCondition::BoundaryCondition(int x) { this->bc_internal.resize(DIM_1D, {0, 0}); - this->special_cells.resize(x, {BC_UNSET, 0}); this->dim = 1; // this value is actually unused this->maxsize = 1; @@ -24,7 +23,6 @@ tug::bc::BoundaryCondition::BoundaryCondition(int x) { tug::bc::BoundaryCondition::BoundaryCondition(int x, int y) { this->maxsize = (x >= y ? x : y); this->bc_internal.resize(DIM_2D * maxsize, {0, 0}); - this->special_cells.resize(x * y, {BC_UNSET, 0}); this->dim = 2; this->sizes[X_DIM] = x; @@ -126,10 +124,25 @@ auto tug::bc::BoundaryCondition::getInnerRow(uint32_t i) const -> bc_vec { throw_out_of_range("Index is out of range"); } - auto start = this->special_cells.begin() + (i * this->sizes[X_DIM]); - auto end = this->special_cells.begin() + ((i + 1) * this->sizes[X_DIM]); + bc_vec row(this->sizes[X_DIM], {tug::bc::BC_UNSET, 0}); - bc_vec row(start, end); + if (this->inner_cells.empty()) { + return row; + } + + uint32_t index_min = i * this->sizes[X_DIM]; + uint32_t index_max = ((i + 1) * this->sizes[X_DIM]) - 1; + + for (auto const &cell : this->inner_cells) { + if (cell.first < index_min) { + continue; + } + if (cell.first > index_max) { + break; + } + + row[cell.first - index_min] = cell.second; + } return row; } @@ -142,12 +155,55 @@ auto tug::bc::BoundaryCondition::getInnerCol(uint32_t i) const -> bc_vec { throw_out_of_range("Index is out of range"); } - bc_vec col; - col.reserve(this->sizes[Y_DIM]); + bc_vec col(this->sizes[Y_DIM], {tug::bc::BC_UNSET, 0}); - for (int j = 0; j < this->sizes[Y_DIM]; i += this->sizes[X_DIM], j++) { - col[j] = this->special_cells[i]; + if (this->inner_cells.empty()) { + return col; + } + + for (auto const &cell : this->inner_cells) { + if (cell.first % this->sizes[X_DIM] == i) { + col[cell.first / this->sizes[X_DIM]] = cell.second; + } } return col; } + +void tug::bc::BoundaryCondition::setInnerBC(boundary_condition bc, int x, + int y = 0) { + if (x >= this->sizes[X_DIM] || y >= this->sizes[Y_DIM]) { + throw_out_of_range("One input parameter is out of range"); + } + uint32_t index = x * this->sizes[Y_DIM] + y; + auto it = this->inner_cells.find(index); + + if (it != this->inner_cells.end()) { + it->second = bc; + return; + } + + this->inner_cells.insert({index, bc}); +} + +void tug::bc::BoundaryCondition::unsetInnerBC(int x, int y) { + uint32_t index = x * this->sizes[Y_DIM] + y; + this->inner_cells.erase(index); +} + +auto tug::bc::BoundaryCondition::getInnerBC(int x, int y = 0) + -> boundary_condition { + if (x >= this->sizes[X_DIM] || y >= this->sizes[Y_DIM]) { + throw_out_of_range("One input parameter is out of range"); + } + + uint32_t index = x * this->sizes[Y_DIM] + y; + + auto it = this->inner_cells.find(index); + + if (it != this->inner_cells.end()) { + return it->second; + } + + return {tug::bc::BC_UNSET, 0}; +} diff --git a/test/testBoundaryCondition.cpp b/test/testBoundaryCondition.cpp index 3eda557..50ebc4a 100644 --- a/test/testBoundaryCondition.cpp +++ b/test/testBoundaryCondition.cpp @@ -98,22 +98,22 @@ TEST_CASE("1D special inner grid cells") { BoundaryCondition bc(5); boundary_condition bc_set = {BC_TYPE_CONSTANT, BC_CONST_VALUE}; - SUBCASE("valid set") { CHECK_NOTHROW(bc(BC_INNER, 0) = bc_set); } + SUBCASE("valid set") { CHECK_NOTHROW(bc.setInnerBC(bc_set, 0, 0)); } SUBCASE("valid get") { - bc(BC_INNER, 0) = bc_set; - CHECK_EQ(bc(BC_INNER, 0).type, bc_set.type); + bc.setInnerBC(bc_set, 0, 0); + CHECK_EQ(bc.getInnerBC(0, 0).type, bc_set.type); } SUBCASE("invalid get") { - CHECK_EQ(bc(BC_INNER, 1).type, BC_UNSET); - CHECK_THROWS(bc(BC_INNER, 5)); + CHECK_EQ(bc.getInnerBC(1, 0).type, BC_UNSET); + CHECK_THROWS(bc.getInnerBC(0, 1)); } - SUBCASE("invalid set") { CHECK_THROWS(bc(BC_INNER, 5) = bc_set); } + SUBCASE("invalid set") { CHECK_THROWS(bc.setInnerBC(bc_set, 0, 1)); } SUBCASE("valid row getter") { - bc(BC_INNER, 1) = bc_set; + bc.setInnerBC(bc_set, 1, 0); bc_vec ret = bc.getInnerRow(0); @@ -130,23 +130,23 @@ TEST_CASE("2D special inner grid cells") { BoundaryCondition bc(5, 5); boundary_condition bc_set = {BC_TYPE_CONSTANT, BC_CONST_VALUE}; - SUBCASE("valid set") { CHECK_NOTHROW(bc(BC_INNER, 0) = bc_set); } + SUBCASE("valid set") { CHECK_NOTHROW(bc.setInnerBC(bc_set, 0, 0)); } SUBCASE("valid get") { - bc(BC_INNER, 0) = bc_set; - CHECK_EQ(bc(BC_INNER, 0).type, bc_set.type); + bc.setInnerBC(bc_set, 0, 0); + CHECK_EQ(bc.getInnerBC(0, 0).type, bc_set.type); } SUBCASE("invalid get") { - CHECK_EQ(bc(BC_INNER, 1).type, BC_UNSET); - CHECK_THROWS(bc(BC_INNER, 25)); + CHECK_EQ(bc.getInnerBC(1, 0).type, BC_UNSET); + CHECK_THROWS(bc.getInnerBC(5, 5)); } - SUBCASE("invalid set") { CHECK_THROWS(bc(BC_INNER, 25) = bc_set); } + SUBCASE("invalid set") { CHECK_THROWS(bc.setInnerBC(bc_set, 5, 5)); } SUBCASE("valid row getter") { - bc(BC_INNER, 0) = bc_set; - bc(BC_INNER, 6) = bc_set; + bc.setInnerBC(bc_set, 0, 0); + bc.setInnerBC(bc_set, 1, 1); bc_vec ret = bc.getInnerRow(0); @@ -160,8 +160,8 @@ TEST_CASE("2D special inner grid cells") { } SUBCASE("valid col getter") { - bc(BC_INNER, 1) = bc_set; - bc(BC_INNER, 5) = bc_set; + bc.setInnerBC(bc_set, 0, 1); + bc.setInnerBC(bc_set, 1, 0); bc_vec ret = bc.getInnerCol(0); @@ -174,6 +174,22 @@ TEST_CASE("2D special inner grid cells") { CHECK_EQ(ret[1].type, BC_UNSET); } + SUBCASE("unset boundary condition") { + bc.setInnerBC(bc_set, 0, 0); + bc.setInnerBC(bc_set, 1, 1); + bc.unsetInnerBC(1, 1); + + bc_vec ret = bc.getInnerRow(1); + + CHECK_EQ(ret[0].type, BC_UNSET); + CHECK_EQ(ret[1].type, BC_UNSET); + + ret = bc.getInnerCol(1); + + CHECK_EQ(ret[0].type, BC_UNSET); + CHECK_EQ(ret[1].type, BC_UNSET); + } + SUBCASE("invalid row getter") { CHECK_THROWS(bc.getInnerRow(5)); } SUBCASE("invalid col getter") { CHECK_THROWS(bc.getInnerCol(5)); } diff --git a/test/testDiffusion.cpp b/test/testDiffusion.cpp index a940d57..74b78f9 100644 --- a/test/testDiffusion.cpp +++ b/test/testDiffusion.cpp @@ -135,7 +135,7 @@ TEST_CASE("2D closed boundaries, 1 constant cell in the middle") { BoundaryCondition bc(N, M); field[MID] = val; - bc(BC_INNER, MID) = {BC_TYPE_CONSTANT, val}; + bc.setInnerBC({BC_TYPE_CONSTANT, val}, N / 2, M / 2); TugInput diffu = setupDiffu(); diffu.setBoundaryCondition(bc);