diff --git a/src/BTCSDiffusion.cpp b/src/BTCSDiffusion.cpp index 251eb59..802c9db 100644 --- a/src/BTCSDiffusion.cpp +++ b/src/BTCSDiffusion.cpp @@ -6,12 +6,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #include @@ -25,15 +19,15 @@ BTCSDiffusion::BTCSDiffusion(int x) : dim_x(x) { this->grid_dim = 1; // per default use Neumann condition with gradient of 0 at the end of the grid - this->bc.resize(2, std::tuple(0,0.)); + this->bc.resize(2, std::tuple(0, 0.)); } BTCSDiffusion::BTCSDiffusion(int x, int y) : dim_x(x), dim_y(y) { // this->grid_dim = 2; // this->bc.reserve(x * 2 + y * 2); - // // per default use Neumann condition with gradient of 0 at the end of the grid - // std::fill(this->bc.begin(), this->bc.end(), -1); + // // per default use Neumann condition with gradient of 0 at the end of the + // grid std::fill(this->bc.begin(), this->bc.end(), -1); } BTCSDiffusion::BTCSDiffusion(int x, int y, int z) : dim_x(x), dim_y(y), dim_z(z) { @@ -42,16 +36,20 @@ BTCSDiffusion::BTCSDiffusion(int x, int y, int z) // TODO: reserve memory for boundary conditions } -void BTCSDiffusion::simulate(std::vector &c, std::vector &alpha, - double timestep) { +void BTCSDiffusion::simulate1D(std::vector &c, double bc_left, + double bc_right, std::vector &alpha) { // calculate dx double dx = 1. / (this->dim_x - 1); // calculate size needed for A matrix and b,x vectors int size = this->dim_x + 2; - Eigen::VectorXd b = Eigen::VectorXd::Constant(size, 0); - Eigen::VectorXd x_out(size); + // set sizes of private and yet allocated vectors + b_vector.resize(size); + x_vector.resize(size); + + // Eigen::VectorXd b = Eigen::VectorXd::Constant(size, 0); + // Eigen::VectorXd x_out(size); /* * Initalization of matrix A @@ -59,42 +57,42 @@ void BTCSDiffusion::simulate(std::vector &c, std::vector &alpha, * https://eigen.tuxfamily.org/dox/group__TutorialSparse.html */ - std::vector tripletList; - tripletList.reserve(c.size() * 3 + bc.size()); + // std::vector tripletList; + // tripletList.reserve(c.size() * 3 + bc.size()); - int A_line = 0; + // int A_line = 0; - // For all concentrations create one row in matrix A - for (int i = 1; i < this->dim_x + 1; i++) { - double sx = (alpha[i - 1] * timestep) / (dx * dx); + // // For all concentrations create one row in matrix A + // for (int i = 1; i < this->dim_x + 1; i++) { + // double sx = (alpha[i - 1] * timestep) / (dx * dx); - tripletList.push_back(T(A_line, i, (-1. - 2. * sx))); + // tripletList.push_back(T(A_line, i, (-1. - 2. * sx))); - tripletList.push_back(T(A_line, i - 1, sx)); - tripletList.push_back(T(A_line, i + 1, sx)); + // tripletList.push_back(T(A_line, i - 1, sx)); + // tripletList.push_back(T(A_line, i + 1, sx)); - b[A_line] = -c[i - 1]; - A_line++; - } + // b[A_line] = -c[i - 1]; + // A_line++; + // } - // append left and right boundary conditions/ghost zones - tripletList.push_back(T(A_line, 0, 1)); + // // append left and right boundary conditions/ghost zones + // tripletList.push_back(T(A_line, 0, 1)); - // if value is -1 apply Neumann condition with given gradient - // TODO: set specific gradient - if (bc[0] == -1) - b[A_line] = c[0]; - // else apply given Dirichlet condition - else - b[A_line] = this->bc[0]; + // // if value is -1 apply Neumann condition with given gradient + // // TODO: set specific gradient + // if (bc[0] == -1) + // b[A_line] = c[0]; + // // else apply given Dirichlet condition + // else + // b[A_line] = this->bc[0]; - A_line++; - tripletList.push_back(T(A_line, size - 1, 1)); - // b[A_line] = bc[1]; - if (bc[1] == -1) - b[A_line] = c[c.size() - 1]; - else - b[A_line] = this->bc[1]; + // A_line++; + // tripletList.push_back(T(A_line, size - 1, 1)); + // // b[A_line] = bc[1]; + // if (bc[1] == -1) + // b[A_line] = c[c.size() - 1]; + // else + // b[A_line] = this->bc[1]; /* * Begin to solve the equation system @@ -103,22 +101,71 @@ void BTCSDiffusion::simulate(std::vector &c, std::vector &alpha, * TODO: remove output */ - Eigen::SparseMatrix A(size, size); - A.setFromTriplets(tripletList.begin(), tripletList.end()); + A_matrix.resize(size, size); + A_matrix.reserve(Eigen::VectorXi::Constant(size, 3)); + + A_matrix.insert(0, 0) = bc_left; + A_matrix.insert(size - 1, size - 1) = bc_right; + + for (int i = 1; i < this->dim_x + 1; i++) { + double sx = (alpha[i - 1] * time_step) / (dx * dx); + + A_matrix.insert(i, i) = -1. - 2. * sx; + A_matrix.insert(i, i - 1) = sx; + A_matrix.insert(i, i + 1) = sx; + + b_vector[i] = -c[i - 1]; + + // tripletList.push_back(T(A_line, i, (-1. - 2. * sx))); + + // tripletList.push_back(T(A_line, i - 1, sx)); + // tripletList.push_back(T(A_line, i + 1, sx)); + + // b[A_line] = -c[i - 1]; + // A_line++; + } + + // Eigen::SparseMatrix A(size, size); + // A.setFromTriplets(tripletList.begin(), tripletList.end()); Eigen::SparseLU, Eigen::COLAMDOrdering> solver; - solver.analyzePattern(A); + solver.analyzePattern(A_matrix); - solver.factorize(A); + solver.factorize(A_matrix); std::cout << solver.lastErrorMessage() << std::endl; - x_out = solver.solve(b); + x_vector = solver.solve(b_vector); - std::cout << std::setprecision(10) << x_out << std::endl << std::endl; + std::cout << std::setprecision(10) << x_vector << std::endl << std::endl; for (int i = 0; i < c.size(); i++) { - c[i] = x_out[i + 1]; + c[i] = x_vector[i + 1]; } } + +void BTCSDiffusion::setTimestep(double time_step) { + this->time_step = time_step; +} + +void BTCSDiffusion::simulate(std::vector &c, + std::vector &alpha) { + if (this->grid_dim == 1) { + double bc_left = getBCFromTuple(0); + double bc_right = getBCFromTuple(1); + + simulate1D(c, bc_left, bc_right, alpha); + } +} + +double BTCSDiffusion::getBCFromTuple(int index) { + double val = std::get<1>(bc[index]); + + return val; +} + +void BTCSDiffusion::setBoundaryCondition(int index, double val, int type) { + std::get<0>(bc[index]) = val; + std::get<1>(bc[index]) = type; +} diff --git a/src/BTCSDiffusion.hpp b/src/BTCSDiffusion.hpp index 8d0bc3e..27b2aed 100644 --- a/src/BTCSDiffusion.hpp +++ b/src/BTCSDiffusion.hpp @@ -2,6 +2,7 @@ #define BTCSDIFFUSION_H_ #include +#include #include #include @@ -11,7 +12,7 @@ */ typedef Eigen::Triplet T; -typedef std::vector> boundary_condition; +typedef std::vector> boundary_condition; /*! * Class implementing a solution for a 1/2/3D diffusion equation using backward @@ -20,9 +21,8 @@ typedef std::vector> boundary_condition; class BTCSDiffusion { public: - - static const int BC_NEUMANN; - static const int BC_DIRICHLET; + static const int BC_NEUMANN; + static const int BC_DIRICHLET; /*! * Create 1D-diffusion module. @@ -56,13 +56,28 @@ public: * @param alpha Vector of diffusioncoefficients for each grid element. * @param timestep Time (in seconds ?) to simulate. */ - void simulate(std::vector &c, std::vector &alpha, - double timestep); + void simulate(std::vector &c, std::vector &alpha); + + void setTimestep(double time_step); + + void setBoundaryCondition(int index, double val, int type); private: + void simulate1D(std::vector &c, double bc_left, double bc_right, + std::vector &alpha); + void simulate2D(std::vector &c); + void simulate3D(std::vector &c); + + double getBCFromTuple(int index); boundary_condition bc; + Eigen::SparseMatrix A_matrix; + Eigen::VectorXd b_vector; + Eigen::VectorXd x_vector; + + double time_step; + int grid_dim; int dim_x; int dim_y; diff --git a/src/main.cpp b/src/main.cpp index 2836c7c..9b376f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,13 +18,16 @@ int main(int argc, char *argv[]) { BTCSDiffusion diffu(x); - diffu.setBoundaryCondition(bc_left, BTCSDiffusion::LEFT); + diffu.setBoundaryCondition(0, 5. * std::pow(10, -6), BTCSDiffusion::BC_DIRICHLET); + diffu.setTimestep(1.); + + // diffu.setBoundaryCondition(bc_left, BTCSDiffusion::LEFT); // we don't need this since Neumann condition with gradient of 0 is set per // default // diffu.setBoundaryCondition(bc_right, BTCSDiffusion::RIGHT); for (int i = 0; i < 100; i++) { - diffu.simulate(input, alpha, 1.); + diffu.simulate(input, alpha); } return 0;