diff --git a/examples/main_1D.cpp b/examples/main_1D.cpp index 2978af7..1b143fc 100644 --- a/examples/main_1D.cpp +++ b/examples/main_1D.cpp @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) { std::vector alpha(n, 1e-1); std::vector field(n, 1e-6); - BTCSBoundaryCondition bc; + BTCSBoundaryCondition bc(n); // create instance of diffusion module BTCSDiffusion diffu(dim); diff --git a/include/grid/BTCSBoundaryCondition.hpp b/include/grid/BTCSBoundaryCondition.hpp index 90fe9f8..7e1c9d4 100644 --- a/include/grid/BTCSBoundaryCondition.hpp +++ b/include/grid/BTCSBoundaryCondition.hpp @@ -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 bc_tuple; +typedef std::vector 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 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"); diff --git a/src/BTCSBoundaryCondition.cpp b/src/BTCSBoundaryCondition.cpp index 9ee8103..ec46c1d 100644 --- a/src/BTCSBoundaryCondition.cpp +++ b/src/BTCSBoundaryCondition.cpp @@ -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 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; +} diff --git a/test/testBoundaryCondition.cpp b/test/testBoundaryCondition.cpp index 58aa189..7c44224 100644 --- a/test/testBoundaryCondition.cpp +++ b/test/testBoundaryCondition.cpp @@ -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") {