perf: represent inner boundary conditions with a std::map

refactor: inner boundary conditions are now accessible via methods

test: update test cases
This commit is contained in:
Max Lübke 2022-09-08 12:46:26 +02:00
parent 94e83b5eb8
commit 592f59dbc5
4 changed files with 126 additions and 40 deletions

View File

@ -3,6 +3,7 @@
#include <array>
#include <bits/stdint-uintn.h>
#include <map>
#include <stdexcept>
#include <stdint.h>
#include <vector>
@ -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<boundary_condition> bc_internal;
bc_vec special_cells;
std::map<uint32_t, boundary_condition> 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");

View File

@ -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};
}

View File

@ -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)); }

View File

@ -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);