TugJulia/include/tug/BoundaryCondition.hpp
2023-06-06 10:10:12 +02:00

284 lines
8.2 KiB
C++

#ifndef BOUNDARYCONDITION_H_
#define BOUNDARYCONDITION_H_
#include <array>
#include <map>
#include <stdexcept>
#include <stdint.h>
#include <vector>
typedef uint8_t bctype;
namespace tug {
namespace bc {
enum {
// flux = Neumann? Cauchy combination of Neumann and Dirichlet?
BC_TYPE_CLOSED, /**< Defines a closed boundary condition (special case of Neumann 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 {
BC_SIDE_LEFT, /**< Defines boundary conditions for the left side of the grid.
*/
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_INNER
};
/**
* Defines the boundary condition type and according value.
* QUESTION: For what is the struct bc necessary?
*/
typedef struct boundary_condition_s {
bctype type; /**< Type of the boundary condition */
double value; /**< Value of the boundary condition. Either a concrete value of
concentration for BC_TYPE_CONSTANT or gradient when type is
BC_TYPE_FLUX. Unused if BC_TYPE_CLOSED.*/
} boundary_condition;
/**
* 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.
*/
class BoundaryCondition {
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
*/
BoundaryCondition(int x);
/**
* Creates a new instance with 4 * max(x,y) elements. Used to describe the
* boundary conditions for 2D grids. NOTE: On non-squared grids there are more
* elements than needed and no exception is thrown if some index exceeding
* grid limits.
*
* QUESTION: why not use non-squared grids with the correct size?
*
* \param x Number of grid cells in x-direction
* \param y Number of grid cells in y-direction
*
*/
BoundaryCondition(int x, int y);
/**
* Sets the boundary condition for a specific side of the grid.
*
* \param side Side for which the given boundary condition should be set.
* \param input_bc Instance of struct boundary_condition with desired boundary
* condition.
*
* \throws std::invalid_argument Indicates wrong dimensions of the grid.
* \throws std::out_of_range Indicates a out of range value for side.
*/
void setSide(uint8_t side, boundary_condition &input_bc);
/**
* Sets the boundary condition for a specific side of the grid.
*
* \param side Side for which the given boundary condition should be set.
* \param input_bc Vector of boundary conditions for specific side.
*
* \throws std::invalid_argument Indicates wrong dimensions of the grid.
* \throws std::out_of_range Indicates a out of range value for side or
* invalid size of input vector.
*/
void setSide(uint8_t side, std::vector<boundary_condition> &input_bc);
/**
* Returns a vector of boundary conditions of given side. Can be used to set
* custom boundary conditions and set back via setSide() with vector input.
*
* \param side Side which boundary conditions should be returned
*
* \returns Vector of boundary conditions
*
* \throws std::invalid_argument If given dimension is less or equal to 1.
* \throws std::out_of_range Indicates a out of range value for side.
*/
auto getSide(uint8_t side) -> std::vector<boundary_condition>;
/**
* Get both boundary conditions of a given row (left and right).
*
* \param i Index of row
*
* \returns Left and right boundary values as an array (defined as data
* type bc_tuple).
*/
auto row_boundary(uint32_t i) const -> bc_tuple;
/**
* Get both boundary conditions of a given column (top and bottom).
*
* \param i Index of column
*
* \returns Top and bottom boundary values as an array (defined as data
* type bc_tuple).
*/
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.
*
* \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.
*
* \param type Type of the boundary condition.
* \param value According value of condition.
*
* \returns Instance of boundary_condition
*/
static boundary_condition returnBoundaryCondition(bctype type, double value) {
return {type, value};
}
private:
std::vector<boundary_condition> bc_internal;
std::map<uint32_t, boundary_condition> inner_cells;
uint8_t dim;
std::array<uint32_t, 2> sizes;
uint32_t maxsize;
uint32_t maxindex;
enum { X_DIM, Y_DIM };
// TODO combine the 'public' blocks
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(
"Only 1D grid support 1 parameter in operator");
}
if (side > 1) {
throw std::out_of_range("1D index out of range");
}
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 (dim != 2) {
throw std::invalid_argument(
"Only 2D grids support 2 parameters in operator");
}
if (side > 3) {
throw std::out_of_range("2D index out of range");
}
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(
"Only 1D grid support 1 parameter in operator");
}
if (side > 1) {
throw std::out_of_range("1D index out of range");
}
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 (dim != 2) {
throw std::invalid_argument("Explicit setting of bc value with 2 "
"parameters is only supported for 2D grids");
}
if (side > 3) {
throw std::out_of_range("2D index out of range");
}
return bc_internal[side * maxsize + i];
}
};
} // namespace bc
} // namespace tug
#endif // BOUNDARYCONDITION_H_