5#ifndef OPENFPM_PDATA_DCPSE_SOLVER_HPP
6#define OPENFPM_PDATA_DCPSE_SOLVER_HPP
10#include "DCPSE_op.hpp"
11#include "Matrix/SparseMatrix.hpp"
12#include "Vector/Vector.hpp"
13#include "NN/CellList/CellDecomposer.hpp"
14#include "Vector/Vector_util.hpp"
15#include "Vector/vector_dist.hpp"
16#include "Solvers/umfpack_solver.hpp"
17#include "Solvers/petsc_solver.hpp"
18#include "util/eq_solve_common.hpp"
38template<
typename Sys_eqs,
40 typename Memory =
typename Sys_eqs::b_part::Memory_type,
45 typename Sys_eqs::SparseMatrix_type A;
48 typename Sys_eqs::Vector_type b;
51 typename Sys_eqs::Vector_type x_ig;
54 typedef typename Sys_eqs::SparseMatrix_type::triplet_type
triplet;
59 typename Sys_eqs::b_part::Decomposition_type,
60 typename Sys_eqs::b_part::Memory_type,
61 layout_base> p_map_type;
98template<
typename options>
102 void construct_pmap(options opt = options_solver::STANDARD) {
106 size_t sz = p_map.size_local();
122 if (opt == options_solver::STANDARD) {
123 b.resize(Sys_eqs::nvar * tot, Sys_eqs::nvar * sz);
124 x_ig.resize(Sys_eqs::nvar * tot, Sys_eqs::nvar * sz);
126 }
else if (opt == options_solver::LAGRANGE_MULTIPLIER) {
127 if (v_cl.
rank() == v_cl.
size() - 1) {
128 b.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * (sz + 1));
129 x_ig.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * (sz + 1));
131 b.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * sz);
132 x_ig.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * sz);
137 if (v_cl.
rank() == v_cl.
size() - 1) {
138 b.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz - offset);
139 x_ig.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz - offset);
141 b.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz);
142 x_ig.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz);
152 auto it = p_map.getDomainIterator();
154 while (it.isNext()) {
158 p_map.getPos(key)[i] = parts.
getPos(key)[i];
161 p_map.template getProp<0>(key) = cnt + s_pnt;
168 p_map.template ghost_get<0>();
174 typename Sys_eqs::stype scal;
181 constant_b(
typename Sys_eqs::stype scal) {
194 typename Sys_eqs::stype get(
size_t key) {
200 template<
unsigned int prp_
id>
203 typename Sys_eqs::stype scal;
224 inline typename Sys_eqs::stype get(
size_t key) {
225 return parts.template getProp<prp_id>(key);
233 void consistency(options_solver opt)
240 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__
241 <<
" the term B and the Matrix A for Ax=B must contain the same number of rows " << row
242 <<
"!=" << row_b <<
"\n";
246 if (row_b != p_map.size_local() * Sys_eqs::nvar) {
247 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__ <<
" your system is underdetermined you set "
248 << row_b <<
" conditions " <<
" but i am expecting " << p_map.size_local() * Sys_eqs::nvar
256 if (v_cl.
rank() == v_cl.
size()-1 && opt == options_solver::LAGRANGE_MULTIPLIER) {
257 nz_rows.resize(row_b+Sys_eqs::nvar);
260 nz_rows.resize(row_b);
263 for (
size_t i = 0; i < trpl.
size(); i++) {
264 if (trpl.get(i).row() - s_pnt * Sys_eqs::nvar >= nz_rows.
size()) {
265 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__
266 <<
" It seems that you are setting colums that does not exist \n";
268 if (trpl.get(i).value() != 0) { nz_rows.get(trpl.get(i).row() - s_pnt * Sys_eqs::nvar) =
true; }
276 if (v_cl.
rank() == v_cl.
size()-1 && opt == options_solver::LAGRANGE_MULTIPLIER) {
277 nz_cols.resize(row_b+Sys_eqs::nvar);
280 nz_cols.resize(row_b);
283 for (
size_t i = 0; i < trpl.
size(); i++) {
284 if (trpl.get(i).value() != 0) { nz_cols.get(trpl.get(i).col()) =
true; }
288 for (
size_t i = 0; i < nz_rows.
size(); i++) {
289 if (nz_rows.get(i) ==
false) {
290 std::cerr <<
"Error: " << __FILE__ <<
":" << __LINE__ <<
" Ill posed matrix row " << i
291 <<
" is not filled " <<
" equation: " <<
"\n";
296 for (
size_t i = 0; i < nz_cols.
size(); i++) {
297 if (nz_cols.get(i) ==
false)
298 std::cerr <<
"Error: " << __FILE__ <<
":" << __LINE__ <<
" Ill posed matrix colum " << i
299 <<
" is not filled\n";
311 template<
typename solType,
typename expr_type>
312 void copy_impl(solType & x, expr_type exp,
unsigned int comp)
314 auto & parts = exp.getVector();
318 while (it.isNext()) {
320 exp.value(p) = x(p.getKey() * Sys_eqs::nvar + comp + s_pnt * Sys_eqs::nvar);
325 template<
typename solType,
typename exp1,
typename ... othersExp>
326 void copy_nested(solType &x,
unsigned int &comp, exp1 exp, othersExp ... exps) {
327 copy_impl(x, exp, comp);
330 copy_nested(x, comp, exps ...);
334 template<
typename solType,
typename exp1>
335 void copy_nested(solType &x,
unsigned int &comp, exp1 exp) {
336 copy_impl(x, exp, comp);
379 template<
typename ... expr_type>
380 void solve(expr_type ... exps) {
381 if (
sizeof...(exps) != Sys_eqs::nvar) {
382 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
383 dimensionality, I am expecting " << Sys_eqs::nvar <<
384 " properties " << std::endl;
386 typename Sys_eqs::solver_type solver;
388 auto x = solver.solve(getA(opt), getB(opt));
390 unsigned int comp = 0;
391 copy_nested(x, comp, exps ...);
402 template<
typename SolverType,
typename ... expr_type>
403 void solve_with_solver(SolverType &solver, expr_type ... exps) {
406 if (
sizeof...(exps) != Sys_eqs::nvar) {
407 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
408 dimensionality, I am expecting " << Sys_eqs::nvar <<
409 " properties " << std::endl;
412 auto x = solver.solve(getA(opt), getB(opt));
414 unsigned int comp = 0;
415 copy_nested(x, comp, exps ...);
426 template<
typename SolverType,
typename ... expr_type>
427 void solve_with_solver_ig(SolverType &solver,expr_type ... exps) {
430 if (
sizeof...(exps) != Sys_eqs::nvar) {
431 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
432 dimensionality, I am expecting " << Sys_eqs::nvar <<
433 " properties " << std::endl;
436 auto x = solver.solve(getA(opt),get_x_ig(opt),getB(opt));
438 unsigned int comp = 0;
439 copy_nested(x, comp, exps ...);
450 template<
typename SolverType,
typename ... expr_type>
451 void solve_with_solver_successive(SolverType &solver,expr_type ... exps) {
454 if (
sizeof...(exps) != Sys_eqs::nvar) {
455 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
456 dimensionality, I am expecting " << Sys_eqs::nvar <<
457 " properties " << std::endl;
460 auto x = solver.solve_successive(getB(opt));
462 unsigned int comp = 0;
463 copy_nested(x, comp, exps ...);
474 template<
typename SolverType,
typename ... expr_type>
475 void solve_with_solver_ig_successive(SolverType &solver,expr_type ... exps) {
478 if (
sizeof...(exps) != Sys_eqs::nvar) {
479 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
480 dimensionality, I am expecting " << Sys_eqs::nvar <<
481 " properties " << std::endl;
484 auto x = solver.solve_successive(get_x_ig(opt),getB(opt));
486 unsigned int comp = 0;
487 copy_nested(x, comp, exps ...);
522 template<
typename SolverType,
typename ... expr_type>
523 void solve_with_default_nullspace_solver(SolverType &solver, expr_type ... exps) {
526 if (
sizeof...(exps) != Sys_eqs::nvar) {
527 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
528 dimensionality, I am expecting " << Sys_eqs::nvar <<
529 " properties " << std::endl;
532 auto x = solver.with_nullspace_solve(getA(opt), getB(opt));
534 unsigned int comp = 0;
535 copy_nested(x, comp, exps ...);
545 template<
typename SolverType,
typename ... expr_type>
546 void try_solve_with_solver(SolverType &solver, expr_type ... exps) {
547 if (
sizeof...(exps) != Sys_eqs::nvar) {
548 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\
549 dimensionality, I am expecting " << Sys_eqs::nvar <<
550 " properties " << std::endl;
553 auto x = solver.try_solve(getA(opt), getB(opt));
555 unsigned int comp = 0;
556 copy_nested(x, comp, exps ...);
568 void reset(
particles_type &part, options_solver opt = options_solver::STANDARD)
578 A.getMatrixTriplets().clear();
589 A.getMatrixTriplets().clear();
599 DCPSE_scheme(
particles_type &part, options_solver opt = options_solver::STANDARD)
600 : parts(part), p_map(part.getDecomposition(), 0), row(0), row_b(0), opt(opt) {
626 template<
typename T,
typename index_type,
unsigned int prp_
id>
630 auto itd = subset.template getIteratorElements<0>();
632 variable_b<prp_id> vb(parts);
634 impose_git(op, vb,
id.getId(), itd);
647 template<
typename index_type,
unsigned int prp_
id>
651 auto itd = subset.template getIteratorElements<0>();
653 variable_b<prp_id> vb(parts);
655 impose_git_b(vb,
id.getId(), itd);
668 template<
typename index_type,
unsigned int prp_
id>
672 auto itd = subset.template getIteratorElements<0>();
674 variable_b<prp_id>
vx(parts);
676 impose_git_x(
vx,
id.getId(), itd);
692 template<typename T, typename index_type, typename RHS_type, typename sfinae = typename std::enable_if<!std::is_fundamental<RHS_type>::type::value>::type>
696 auto itd = subset.template getIteratorElements<0>();
698 impose_git(op, rhs,
id.getId(), itd);
711 template<typename index_type, typename RHS_type, typename sfinae = typename std::enable_if<!std::is_fundamental<RHS_type>::type::value>::type>
715 auto itd = subset.template getIteratorElements<0>();
716 impose_git_b(rhs,
id.getId(), itd);
727 template<typename index_type, typename RHS_type, typename sfinae = typename std::enable_if<!std::is_fundamental<RHS_type>::type::value>::type>
731 auto itd = subset.template getIteratorElements<0>();
732 impose_git_x(rhs,
id.getId(), itd);
748 template<
typename T,
typename index_type>
749 void impose(
const T &op,
751 const typename Sys_eqs::stype num,
753 auto itd = subset.template getIteratorElements<0>();
757 impose_git(op, b,
id.getId(), itd);
770 template<
typename index_type>
772 const typename Sys_eqs::stype num,
774 auto itd = subset.template getIteratorElements<0>();
778 impose_git_b(b,
id.getId(), itd);
792 template<
typename index_type>
794 const typename Sys_eqs::stype num,
796 auto itd = subset.template getIteratorElements<0>();
798 constant_b x_ig(num);
800 impose_git_x(x_ig,
id.getId(), itd);
808 template<
typename options>
809 typename Sys_eqs::SparseMatrix_type &getA(options opt) {
810 if (A.isMatrixFilled())
return A;
811 if (opt == options_solver::STANDARD) {
812 A.resize(tot * Sys_eqs::nvar, tot * Sys_eqs::nvar,
813 p_map.size_local() * Sys_eqs::nvar,
814 p_map.size_local() * Sys_eqs::nvar);
816 else if (opt == options_solver::LAGRANGE_MULTIPLIER) {
817 auto &v_cl = create_vcluster();
820 if (v_cl.
rank() == v_cl.
size() - 1) {
821 A.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * (tot + 1),
822 Sys_eqs::nvar * (p_map.size_local() + 1),
823 Sys_eqs::nvar * (p_map.size_local() + 1));
825 for (
int j = 0; j < Sys_eqs::nvar; j++) {
826 for (
int i = 0; i < tot; i++) {
828 t1.row() = tot * Sys_eqs::nvar + j;
829 t1.col() = i * Sys_eqs::nvar + j;
833 for (
int i = 0; i < p_map.size_local(); i++) {
835 t2.row() = s_pnt * Sys_eqs::nvar + i * Sys_eqs::nvar + j;
836 t2.col() = tot * Sys_eqs::nvar + j;
841 t3.col() = tot * Sys_eqs::nvar + j;
842 t3.row() = tot * Sys_eqs::nvar + j;
847 A.resize(Sys_eqs::nvar * (tot + 1), Sys_eqs::nvar * (tot + 1),
848 p_map.size_local() * Sys_eqs::nvar,
849 p_map.size_local() * Sys_eqs::nvar);
850 for (
int j = 0; j < Sys_eqs::nvar; j++) {
851 for (
int i = 0; i < p_map.size_local(); i++) {
853 t2.row() = s_pnt * Sys_eqs::nvar + i * Sys_eqs::nvar + j;
854 t2.col() = tot * Sys_eqs::nvar + j;
862 auto &v_cl = create_vcluster();
863 if (v_cl.
rank() == v_cl.
size() - 1) {
864 A.resize(tot * Sys_eqs::nvar - offset, tot * Sys_eqs::nvar - offset,
865 p_map.size_local() * Sys_eqs::nvar - offset,
866 p_map.size_local() * Sys_eqs::nvar - offset);
869 A.resize(tot * Sys_eqs::nvar - offset, tot * Sys_eqs::nvar - offset,
870 p_map.size_local() * Sys_eqs::nvar,
871 p_map.size_local() * Sys_eqs::nvar);
886 typename Sys_eqs::Vector_type &getB(options_solver opt = options_solver::STANDARD) {
890 if (opt == options_solver::LAGRANGE_MULTIPLIER) {
891 auto &v_cl = create_vcluster();
892 if (v_cl.
rank() == v_cl.
size() - 1) {
893 for(
int j=0;j<Sys_eqs::nvar;j++)
894 {b(tot * Sys_eqs::nvar+j) = 0;}
905 typename Sys_eqs::Vector_type &get_x_ig(options_solver opt = options_solver::STANDARD) {
909 if (opt == options_solver::LAGRANGE_MULTIPLIER) {
910 auto &v_cl = create_vcluster();
911 if (v_cl.
rank() == v_cl.
size() - 1) {
912 for(
int j=0;j<Sys_eqs::nvar;j++)
913 {x_ig(tot * Sys_eqs::nvar+j) = 0;}
920 template<
typename bop,
typename iterator>
921 void impose_git_b(bop num,
923 const iterator &it_d) {
926 while (it.isNext()) {
930 b(p_map.template getProp<0>(key) * Sys_eqs::nvar +
id) = num.get(key);
942 template<
typename xop,
typename iterator>
943 void impose_git_x(xop num,
945 const iterator &it_d) {
948 while (it.isNext()) {
952 x_ig(p_map.template getProp<0>(key) * Sys_eqs::nvar +
id) = num.get(key);
980 template<
typename T,
typename bop,
typename iterator>
981 void impose_git(
const T &op,
984 const iterator &it_d) {
994 while (it.isNext()) {
999 typename Sys_eqs::stype coeff = 1.0;
1000 op.template value_nz<Sys_eqs>(p_map, key, cols, coeff, 0);
1003 bool is_diag =
false;
1006 for (
auto it2 = cols.begin(); it2 != cols.end(); ++it2) {
1008 trpl.last().row() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
1009 trpl.last().col() = it2->first;
1010 trpl.last().value() = it2->second;
1011 if (trpl.last().row() == trpl.last().col())
1016 if (is_diag ==
false)
1019 trpl.last().row() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
1020 trpl.last().col() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
1021 trpl.last().value() = 0.0;
1023 b(p_map.template getProp<0>(key) * Sys_eqs::nvar +
id) = num.get(key);
1040template<
typename Sys_eqs,
typename particles_type>
using DCPSE_scheme_gpu = DCPSE_scheme<Sys_eqs,particles_type,CudaMemory,memory_traits_inte>;
1042#include "DCPSE/DCPSE_op/EqnsStruct.hpp"
void execute()
Execute all the requests.
size_t rank()
Get the process unit id.
size_t size()
Get the total number of processors.
void sum(T &num)
Sum the numbers across all processors and get the result.
size_t getProcessUnitID()
Get the process unit id.
size_t getProcessingUnits()
Get the total number of processors.
bool allGather(T &send, openfpm::vector< T, Mem, gr > &v)
Gather the data from all processors.
Implementation of VCluster class.
Implementation of 1-D std::vector like structure.
vect_dist_key_dx get()
Get the actual key.
size_t size_local() const
return the local size of the vector
void resize(size_t rs)
Resize the vector (locally)
static const unsigned int dims
template parameters typedefs
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Transform the boost::fusion::vector into memory specification (memory_traits)
It model an expression expr1 * expr2.
static void value(const grid_dist_id< Sys_eqs::dims, typename Sys_eqs::stype, aggregate< size_t >, typename Sys_eqs::b_grid::decomposition::extended_type > &g_map, grid_dist_key_dx< Sys_eqs::dims > &kmap, const grid_sm< Sys_eqs::dims, void > &gs, typename Sys_eqs::stype(&spacing)[Sys_eqs::dims], std::unordered_map< long int, typename Sys_eqs::stype > &cols, typename Sys_eqs::stype coeff)
Calculate which colums of the Matrix are non zero.
It store the non zero elements of the matrix.