feat: add setting of inner boundary conditions

It is possible to define inner grid cells with a type of either CLOSED,
FLUX, CLOSED or UNSET.
This commit is contained in:
Max Lübke 2022-08-04 13:42:24 +02:00
parent fd7e2f5b63
commit b6eb212bcb
4 changed files with 131 additions and 22 deletions

View File

@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
std::vector<double> alpha(n, 1e-1);
std::vector<double> field(n, 1e-6);
BTCSBoundaryCondition bc;
BTCSBoundaryCondition bc(n);
// create instance of diffusion module
BTCSDiffusion diffu(dim);

View File

@ -12,9 +12,10 @@ typedef uint8_t bctype;
namespace Diffusion {
enum {
BC_TYPE_CLOSED, /**< Defines a closed/Neumann boundary condition. */
BC_TYPE_FLUX, /**< Defines a flux/Cauchy boundary condition. */
BC_TYPE_CONSTANT /**< Defines a constant/Dirichlet boundary condition. */
BC_TYPE_CLOSED, /**< Defines a closed/Neumann boundary condition. */
BC_TYPE_FLUX, /**< Defines a flux/Cauchy boundary condition. */
BC_TYPE_CONSTANT, /**< Defines a constant/Dirichlet boundary condition. */
BC_UNSET /**< Indicates undefined boundary condition*/
};
enum {
@ -23,7 +24,9 @@ enum {
BC_SIDE_RIGHT, /**< Defines boundary conditions for the right side of the
grid. */
BC_SIDE_TOP, /**< Defines boundary conditions for the top of the grid. */
BC_SIDE_BOTTOM /**< Defines boundary conditions for the bottom of the grid. */
BC_SIDE_BOTTOM, /**< Defines boundary conditions for the bottom of the grid.
*/
BC_INNER
};
/**
@ -40,6 +43,7 @@ typedef struct boundary_condition_s {
* Represents both boundary conditions of a row/column.
*/
typedef std::array<boundary_condition, 2> bc_tuple;
typedef std::vector<boundary_condition> bc_vec;
/**
* Class to define the boundary condition of a grid.
@ -49,8 +53,10 @@ public:
/**
* Creates a new instance with two elements. Used when defining boundary
* conditions of 1D grids.
*
* \param x Number of grid cells in x-direction
*/
BTCSBoundaryCondition();
BTCSBoundaryCondition(int x);
/**
* Creates a new instance with 4 * max(x,y) elements. Used to describe the
@ -121,6 +127,24 @@ public:
*/
auto col_boundary(uint32_t i) const -> bc_tuple;
/**
* Get a row of field and its inner boundary conditions.
*
* \param i Index of the row starting at 0.
*
* \returns Row of the inner boundary conditions of the field.
*/
auto getInnerRow(uint32_t i) const -> bc_vec;
/**
* Get a column of field and its inner boundary conditions.
*
* \param i Index of the column starting at 0.
*
* \returns Column of the inner boundary conditions of the field.
*/
auto getInnerCol(uint32_t i) const -> bc_vec;
/**
* Create an instance of boundary_condition data type. Can be seen as a helper
* function.
@ -137,12 +161,24 @@ public:
private:
std::vector<boundary_condition> bc_internal;
bc_vec special_cells;
uint8_t dim;
uint32_t sizes[2];
uint32_t maxsize;
uint32_t maxindex;
enum { X_DIM, Y_DIM };
public:
/**
* Returns the left/right boundary condition for 1D grid.
*
* \param side Side of the boundary condition to get.
*
* \returns Boundary condition
*/
boundary_condition operator()(uint8_t side) const {
if (dim != 1) {
throw std::invalid_argument(
@ -154,7 +190,21 @@ public:
return bc_internal[side];
}
/**
* Returns the boundary condition of a given side for 2D grids.
*
* \param side Side of the boundary condition to get.
* \param i Index of the boundary condition.
*
* \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");
@ -165,6 +215,13 @@ public:
return bc_internal[side * maxsize + i];
}
/**
* Returns the left/right boundary condition for 1D grid.
*
* \param side Side of the boundary condition to get.
*
* \returns Boundary condition
*/
boundary_condition &operator()(uint8_t side) {
if (dim != 1) {
throw std::invalid_argument(
@ -176,7 +233,21 @@ public:
return bc_internal[side];
}
/**
* Returns the boundary condition of a given side for 2D grids.
*
* \param side Side of the boundary condition to get.
* \param i Index of the boundary condition.
*
* \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

@ -8,23 +8,29 @@
constexpr uint8_t DIM_1D = 2;
constexpr uint8_t DIM_2D = 4;
Diffusion::BTCSBoundaryCondition::BTCSBoundaryCondition() {
Diffusion::BTCSBoundaryCondition::BTCSBoundaryCondition(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;
this->sizes[0] = 1;
this->sizes[1] = 0;
this->sizes[X_DIM] = 1;
this->sizes[Y_DIM] = x;
this->maxindex = x - 1;
}
Diffusion::BTCSBoundaryCondition::BTCSBoundaryCondition(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[0] = x;
this->sizes[1] = y;
this->sizes[X_DIM] = x;
this->sizes[Y_DIM] = y;
this->maxindex = (x * y) - 1;
}
void Diffusion::BTCSBoundaryCondition::setSide(
@ -38,8 +44,8 @@ void Diffusion::BTCSBoundaryCondition::setSide(
uint32_t size =
(side == Diffusion::BC_SIDE_LEFT || side == Diffusion::BC_SIDE_RIGHT
? this->sizes[0]
: this->sizes[1]);
? this->sizes[X_DIM]
: this->sizes[Y_DIM]);
for (uint32_t i = 0; i < size; i++) {
this->bc_internal[side * maxsize + i] = input_bc;
@ -57,8 +63,8 @@ void Diffusion::BTCSBoundaryCondition::setSide(
uint32_t size =
(side == Diffusion::BC_SIDE_LEFT || side == Diffusion::BC_SIDE_RIGHT
? this->sizes[0]
: this->sizes[1]);
? this->sizes[X_DIM]
: this->sizes[Y_DIM]);
if (input_bc.size() > size) {
throw_out_of_range("Input vector is greater than maximum excpected value");
@ -80,8 +86,8 @@ auto Diffusion::BTCSBoundaryCondition::getSide(uint8_t side)
uint32_t size =
(side == Diffusion::BC_SIDE_LEFT || side == Diffusion::BC_SIDE_RIGHT
? this->sizes[0]
: this->sizes[1]);
? this->sizes[X_DIM]
: this->sizes[Y_DIM]);
std::vector<Diffusion::boundary_condition> out(size);
@ -97,7 +103,7 @@ auto Diffusion::BTCSBoundaryCondition::col_boundary(uint32_t i) const
if (this->dim == 1) {
throw_invalid_argument("Access of column requires at least 2D grid");
}
if (i >= this->sizes[1]) {
if (i >= this->sizes[Y_DIM]) {
throw_out_of_range("Index out of range");
}
@ -107,10 +113,42 @@ auto Diffusion::BTCSBoundaryCondition::col_boundary(uint32_t i) const
auto Diffusion::BTCSBoundaryCondition::row_boundary(uint32_t i) const
-> Diffusion::bc_tuple {
if (i >= this->sizes[0]) {
if (i >= this->sizes[X_DIM]) {
throw_out_of_range("Index out of range");
}
return {this->bc_internal[BC_SIDE_LEFT * this->maxsize + i],
this->bc_internal[BC_SIDE_RIGHT * this->maxsize + i]};
}
auto Diffusion::BTCSBoundaryCondition::getInnerRow(uint32_t i) const -> bc_vec {
if (i >= this->sizes[X_DIM]) {
throw_out_of_range("Index is out of range");
}
bc_vec::const_iterator start =
this->special_cells.begin() + (i * this->sizes[Y_DIM]);
bc_vec::const_iterator end =
this->special_cells.begin() + ((i + 1) * this->sizes[Y_DIM]);
bc_vec row(start, end);
return row;
}
auto Diffusion::BTCSBoundaryCondition::getInnerCol(uint32_t i) const -> bc_vec {
if (this->dim != 2) {
throw_invalid_argument("getInnerCol is only applicable for 2D grids");
} else if (i >= this->sizes[X_DIM]) {
throw_out_of_range("Index is out of range");
}
bc_vec col;
col.reserve(this->sizes[X_DIM]);
for (int j = 0; j < this->sizes[X_DIM]; i += this->sizes[Y_DIM], j++) {
col[j] = this->special_cells[i];
}
return col;
}

View File

@ -7,7 +7,7 @@ using namespace Diffusion;
TEST_CASE("1D Boundary Condition") {
BTCSBoundaryCondition bc;
BTCSBoundaryCondition bc(5);
boundary_condition bc_set = {BC_TYPE_CONSTANT, BC_CONST_VALUE};
SUBCASE("valid get") { CHECK_EQ(bc(BC_SIDE_LEFT).value, 0); }
@ -50,7 +50,7 @@ TEST_CASE("2D Boundary Condition") {
SUBCASE("valid get") { CHECK_EQ(bc(BC_SIDE_LEFT, 0).value, 0); }
SUBCASE("invalid get") {
CHECK_THROWS(bc(4, 0));
CHECK_THROWS(bc(5, 0));
CHECK_THROWS(bc(BC_SIDE_LEFT));
}
@ -62,7 +62,7 @@ TEST_CASE("2D Boundary Condition") {
SUBCASE("invalid set") {
CHECK_THROWS(bc(BC_SIDE_LEFT) = bc_set);
CHECK_THROWS(bc(4, 0) = bc_set);
CHECK_THROWS(bc(5, 0) = bc_set);
}
SUBCASE("call of setSide") {