diff --git a/src/FiniteDifference/FDScheme.hpp b/src/FiniteDifference/FDScheme.hpp index 0488cec1cccae752b8e4b24951f0a00f17a78bda..64d9ad79fd50fabf7e79210292f92fc202ccbfc1 100644 --- a/src/FiniteDifference/FDScheme.hpp +++ b/src/FiniteDifference/FDScheme.hpp @@ -365,7 +365,9 @@ public: // sync the ghost + g_map.write("g_map_before_ghost.vtk"); g_map.template ghost_get<0>(); + g_map.write("g_map_after_ghost.vtk"); // Create a CellDecomposer and calculate the spacing @@ -512,7 +514,7 @@ public: // copy the vector for (size_t i = 0; i < row_b; i++) - B.get(i) = b.get(i); + B.insert(i,b.get(i)); return B; } diff --git a/src/FiniteDifference/eq.hpp b/src/FiniteDifference/eq.hpp index 6d85cc9e6dbff7d37666ac9ffad86b05df36221c..f4af2d96074dca9ffa1628647a55fd97e7ffeb47 100644 --- a/src/FiniteDifference/eq.hpp +++ b/src/FiniteDifference/eq.hpp @@ -11,9 +11,6 @@ #define EQS_FIELD 0 #define EQS_POS 1 -#define STAGGERED_GRID 1 -#define NORMAL_GRID 0 - //#define PERIODIC true //#define NON_PERIODIC false diff --git a/src/FiniteDifference/eq_unit_test.hpp b/src/FiniteDifference/eq_unit_test.hpp index 842692ea3dc09ef5dc66fbeef4d14adad51ead21..6ebf2ab87d16538e09dc3c9d1bbed524c05dacb5 100644 --- a/src/FiniteDifference/eq_unit_test.hpp +++ b/src/FiniteDifference/eq_unit_test.hpp @@ -142,13 +142,13 @@ BOOST_AUTO_TEST_CASE(lid_driven_cavity) //! [lid-driven cavity 2D] // Domain, a rectangle - Box<2,float> domain({0.0,0.0},{3.0,1.0}); + Box<2,float> domain({0.0,0.0},{1.0,1.0}); // Ghost (Not important in this case but required) Ghost<2,float> g(0.01); // Grid points on x=256 and y=64 - long int sz[] = {256,64}; + long int sz[] = {8,8}; size_t szu[2]; szu[0] = (size_t)sz[0]; szu[1] = (size_t)sz[1]; diff --git a/src/FiniteDifference/util/common.hpp b/src/FiniteDifference/util/common.hpp index 4b383d6b795f36c720d7cb17c0a5d579eedd1b34..dc71a5e2e76509966db2b2ec0cb831a851b41965 100644 --- a/src/FiniteDifference/util/common.hpp +++ b/src/FiniteDifference/util/common.hpp @@ -8,6 +8,8 @@ #ifndef OPENFPM_NUMERICS_SRC_UTIL_COMMON_HPP_ #define OPENFPM_NUMERICS_SRC_UTIL_COMMON_HPP_ +#define STAGGERED_GRID 1 +#define NORMAL_GRID 0 template<typename T, typename Sfinae = void> struct has_grid_type: std::false_type {}; diff --git a/src/Matrix/SparseMatrix_Eigen.hpp b/src/Matrix/SparseMatrix_Eigen.hpp index 706c818cb496e0e54106903438833003819d5c40..85bb274cb3256129531908a55b43b3877a77c3a8 100644 --- a/src/Matrix/SparseMatrix_Eigen.hpp +++ b/src/Matrix/SparseMatrix_Eigen.hpp @@ -21,30 +21,49 @@ * */ template<typename T> -struct triplet<T,EIGEN_TRIPLET> +class triplet<T,EIGEN_TRIPLET> { - Eigen::Triplet<T,long int> triplet; + Eigen::Triplet<T,long int> triplet_ei; + +public: long int & row() { - size_t ptr = (size_t)&triplet.row(); + size_t ptr = (size_t)&triplet_ei.row(); return (long int &)*(long int *)ptr; } long int & col() { - size_t ptr = (size_t)&triplet.col(); + size_t ptr = (size_t)&triplet_ei.col(); return (long int &)*(long int *)ptr; } T & value() { - size_t ptr = (size_t)&triplet.value(); + size_t ptr = (size_t)&triplet_ei.value(); return (T &)*(T *)ptr; } + + /*! \brief Constructor from row, colum and value + * + * \param i row + * \param j colum + * \param val value + * + */ + triplet(long int i, long int j, T val) + { + row() = i; + col() = j; + value() = val; + } + + // Default constructor + triplet() {}; }; /* ! \brief Sparse Matrix implementation, that map over Eigen @@ -73,8 +92,6 @@ private: /*! \brief Assemble the matrix * - * \param trpl Matrix in form of triplets - * \param mat Matrix to assemble * */ void assemble() @@ -187,6 +204,16 @@ public: { mat.resize(row,col); } + + /*! \brief Get the row i and the colum j of the Matrix + * + * \return the value of the matrix at row i colum j + * + */ + T operator()(id_t i, id_t j) + { + return mat.coeffRef(i,j); + } }; diff --git a/src/Solvers/umfpack_solver.hpp b/src/Solvers/umfpack_solver.hpp index 826343cd036b6c1727349af46eb647c73ad5ec4e..2d5f67d30d4291851416bd6aeb8a6b09cd477029 100644 --- a/src/Solvers/umfpack_solver.hpp +++ b/src/Solvers/umfpack_solver.hpp @@ -46,16 +46,27 @@ public: */ template<typename impl> static Vector<double> solve(SparseMatrix<double,int,impl> & A, const Vector<double> & b, size_t opt = UMFPACK_NONE) { - Vcluster & v_cl = *global_v_cluster; + Vcluster & vcl = *global_v_cluster; Vector<double> x; + // only master processor solve + Eigen::UmfPackLU<Eigen::SparseMatrix<double,0,int> > solver; - if (v_cl.getProcessUnitID() == 0) - { - Eigen::UmfPackLU<Eigen::SparseMatrix<double,0,int> > solver; + // Collect the matrix on master + auto mat_ei = A.getMat(); + + Eigen::Matrix<double, Eigen::Dynamic, 1> x_ei; + + // Collect the vector on master + auto b_ei = b.getVec(); - solver.compute(A.getMat()); + // Copy b into x, this also copy the information on how to scatter back the information on x + x = b; + + if (vcl.getProcessUnitID() == 0) + { + solver.compute(mat_ei); if(solver.info()!=Eigen::Success) { @@ -64,14 +75,14 @@ public: return x; } - x.getVec() = solver.solve(b.getVec()); + x_ei = solver.solve(b_ei); if (opt & SOLVER_PRINT_RESIDUAL_NORM_INFINITY) { - Vector<double> res; - res.getVec() = A.getMat() * x.getVec() - b.getVec(); + Eigen::Matrix<double, Eigen::Dynamic, 1> res; + res = mat_ei * x_ei - b_ei; - std::cout << "Infinity norm: " << res.getVec().lpNorm<Eigen::Infinity>() << "\n"; + std::cout << "Infinity norm: " << res.lpNorm<Eigen::Infinity>() << "\n"; } if (opt & SOLVER_PRINT_DETERMINANT) @@ -79,9 +90,12 @@ public: std::cout << " Determinant: " << solver.determinant() << "\n"; } - // Vector is only on master, scatter back the information - x.scatter(); + x = x_ei; } + + // Vector is only on master, scatter back the information + x.scatter(); + return x; } }; diff --git a/src/Vector/Vector.hpp b/src/Vector/Vector.hpp index 8277376953f5284a128bed93d79f68a59d12e055..43469dba28c9163c2aab486164ecd50beab0beaa 100644 --- a/src/Vector/Vector.hpp +++ b/src/Vector/Vector.hpp @@ -8,6 +8,19 @@ #ifndef OPENFPM_NUMERICS_SRC_VECTOR_VECTOR_HPP_ #define OPENFPM_NUMERICS_SRC_VECTOR_VECTOR_HPP_ +#include <Eigen/Sparse> + +/*! \brief It store one row value of a vector + * + * Given a row, store a value + * + * + */ +template<typename T, unsigned int impl> +class rval +{ +}; + /* ! \brief Sparse Matrix implementation * diff --git a/src/Vector/Vector_eigen.hpp b/src/Vector/Vector_eigen.hpp index f0d5c2b8cc6d8a1eeab61a895af9ea00de094d17..4ef615b6c7eb9c825515ef6ea3523038d0f11078 100644 --- a/src/Vector/Vector_eigen.hpp +++ b/src/Vector/Vector_eigen.hpp @@ -13,13 +13,80 @@ #include <fstream> #include "Vector_eigen_util.hpp" #include "Grid/staggered_dist_grid_util.hpp" +#include "Space/Ghost.hpp" +#include "FiniteDifference/util/common.hpp" #include <boost/mpl/vector_c.hpp> +#include <unordered_map> +#define EIGEN_RVAL 1 + +/*! \brief It store one row value of a vector + * + * Given a row, store a value + * + * + */ +template<typename T> +class rval<T,EIGEN_RVAL> +{ + // row + long int r; + + // value + T val; + +public: + + // Get the row + long int & row() + { + return r; + } + + // Get the value + T & value() + { + return val; + } + + /*! \brief Default constructor + * + */ + rval() {} + + /*! \brief Constructor from row, colum and value + * + * \param i row + * \param val value + * + */ + rval(long int i, T val) + { + row() = i; + value() = val; + } +}; template<typename T> class Vector<T,Eigen::Matrix<T, Eigen::Dynamic, 1>> { - Eigen::Matrix<T, Eigen::Dynamic, 1> v; + mutable Eigen::Matrix<T, Eigen::Dynamic, 1> v; + + // row value vector + mutable openfpm::vector<rval<T,EIGEN_RVAL>> row_val; + mutable openfpm::vector<rval<T,EIGEN_RVAL>> row_val_recv; + + // global to local map + mutable std::unordered_map<size_t,size_t> map; + + // invalid + T invalid; + + // Processors from where we gather + mutable openfpm::vector<size_t> prc; + + //size of each chunk + mutable openfpm::vector<size_t> sz; /*! \brief Check that the size of the iterators match * @@ -169,8 +236,90 @@ class Vector<T,Eigen::Matrix<T, Eigen::Dynamic, 1>> } } + + /*! \brief Here we collect the full matrix on master + * + */ + void collect() const + { + Vcluster & vcl = *global_v_cluster; + + row_val_recv.clear(); + + // here we collect all the triplet in one array on the root node + vcl.SGather(row_val,row_val_recv,prc,sz,0); + + if (vcl.getProcessUnitID() != 0) + row_val.resize(0); + else + row_val.swap(row_val_recv); + + build_map(); + } + + /*! \brief Set the Eigen internal vector + * + * + */ + void setEigen() const + { + // set the vector + + for (size_t i = 0 ; i < row_val.size() ; i++) + v[row_val.get(i).row()] = row_val.get(i).value(); + } + + /*! \brief Build the map + * + * + */ + void build_map() const + { + map.clear(); + + for (size_t i = 0 ; i < row_val.size() ; i++) + map[row_val.get(i).row()] = i; + } + public: + /*! \brief Copy the vector + * + * \param v vector to copy + * + */ + Vector(const Vector<T> & v) + { + this->operator=(v); + } + + /*! \brief Copy the vector + * + * \param v vector to copy + * + */ + Vector(const Vector<T> && v) + { + this->operator=(v); + } + + /*! \brief Create a vector with n elements + * + * \param n number of elements in the vector + * + */ + Vector(size_t n) + { + resize(n); + } + + /*! \brief Create a vector with 0 elements + * + */ + Vector() + { + } + /*! \brief Resize the Vector * * \param row numbers of row @@ -188,9 +337,44 @@ public: * \return reference to the element vector * */ - T & get(size_t i) + void insert(size_t i, T val) { - return v(i); + row_val.add(); + + // Map + map[i] = row_val.size()-1; + + row_val.last().row() = i; + row_val.last().value() = val; + } + + /*! \brief Return a reference to the vector element + * + * \warning The element must exist + * + * \param i element + * + * \return reference to the element vector + * + */ + T & operator()(size_t i) + { + // Search if exist + + std::unordered_map<size_t,size_t>::iterator it = map.find(i); + + if ( it == map.end() ) + { + // Does not exist + + std::cerr << __FILE__ << ":" << __LINE__ << " value does not exist " << std::endl; + + return invalid; + } + else + return row_val.get(it->second).value(); + + return invalid; } /*! \brief Get the Eigen Vector object @@ -200,6 +384,9 @@ public: */ const Eigen::Matrix<T, Eigen::Dynamic, 1> & getVec() const { + collect(); + setEigen(); + return v; } @@ -210,6 +397,9 @@ public: */ Eigen::Matrix<T, Eigen::Dynamic, 1> & getVec() { + collect(); + setEigen(); + return v; } @@ -228,30 +418,28 @@ public: } } - /*! \brief Collect the vector into one processor - * - * Eigen does not have a real parallel vector, so in order to work we have to collect - * the vector in one processor - * - * This function collect the information from all the other processor into one - * - */ - void collect() - { - - } - /*! \brief Scatter the vector information to the other processors * * Eigen does not have a real parallel vector, so in order to work we have to scatter * the vector from one processor to the other * - * This function scatter the information to all the other processors * */ void scatter() { + row_val_recv.clear(); + Vcluster & vcl = *global_v_cluster; + + vcl.SScatter(row_val,row_val_recv,prc,sz,0); + // if we do not receive anything a previous collect has not been performed + // and so nothing is scattered + if (row_val_recv.size() != 0) + { + row_val.clear(); + row_val.add(row_val_recv); + build_map(); + } } /*! \brief Load from file @@ -270,6 +458,51 @@ public: inputf.close(); } + + /*! \brief Copy the vector + * + * \param v vector to copy + * + */ + Vector<T> & operator=(const Vector<T> & v) + { + prc = v.prc; + sz = v.sz; + map = v.map; + row_val = v.row_val; + + return *this; + } + + /*! \brief Copy the vector + * + * \param v vector to copy + * + */ + Vector<T> & operator=(const Vector<T> && v) + { + prc = v.prc; + sz = v.sz; + map = v.map; + row_val = v.row_val; + + return *this; + } + + /*! \brief Copy the vector (it is used for special purpose) + * + * \warning v MUST contain at least all the elements of the vector + * + * \param v base eigen vector to copy + * + */ + Vector<T> & operator=(Eigen::Matrix<T, Eigen::Dynamic, 1> & v) + { + for (size_t i = 0 ; i < row_val.size() ; i++) + row_val.get(i).value() = v(row_val.get(i).row()); + + return *this; + } }; diff --git a/src/Vector/Vector_eigen_util.hpp b/src/Vector/Vector_eigen_util.hpp index da16b2a7868c1b429e6fdb7c4cf08b5664c79a42..221a8600be5e5e4bb819c62ff85b9c2bb294b67e 100644 --- a/src/Vector/Vector_eigen_util.hpp +++ b/src/Vector/Vector_eigen_util.hpp @@ -8,6 +8,8 @@ #ifndef OPENFPM_NUMERICS_SRC_VECTOR_VECTOR_EIGEN_UTIL_HPP_ #define OPENFPM_NUMERICS_SRC_VECTOR_VECTOR_EIGEN_UTIL_HPP_ +#include "Grid/grid_dist_key.hpp" +#include "Space/Shape/HyperCube.hpp" /*! \brief Copy scalar elements * diff --git a/src/main.cpp b/src/main.cpp index 57fb816dcd55bd6455b17767d16396a66b4c6868..8a63fcf886529ad092a5e275a6a60affdd764194 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,8 @@ #include "unit_test_init_cleanup.hpp" +#include "Vector/Vector_unit_tests.hpp" +#include "Matrix/SparseMatrix_unit_tests.hpp" #include "Equations/eq_unit_tests.hpp" #include "FiniteDifference/FDScheme_unit_tests.hpp" #include "FiniteDifference/util/common_test.hpp"