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" 38 template<
typename Sys_eqs,
typename particles_type>
42 typename Sys_eqs::SparseMatrix_type A;
45 typename Sys_eqs::Vector_type b;
48 typedef typename Sys_eqs::SparseMatrix_type::triplet_type
triplet;
85 template<
typename options>
89 void construct_pmap(options opt = options_solver::STANDARD) {
93 size_t sz = p_map.size_local();
109 if (opt == options_solver::STANDARD) {
110 b.resize(Sys_eqs::nvar * tot, Sys_eqs::nvar * sz);
111 }
else if (opt == options_solver::LAGRANGE_MULTIPLIER) {
112 if (v_cl.
rank() == v_cl.
size() - 1) {
113 b.resize(Sys_eqs::nvar * tot + 1, Sys_eqs::nvar * sz + 1);
115 b.resize(Sys_eqs::nvar * tot + 1, Sys_eqs::nvar * sz);
120 if (v_cl.
rank() == v_cl.
size() - 1) {
121 b.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz - offset);
123 b.resize(Sys_eqs::nvar * tot - offset, Sys_eqs::nvar * sz);
133 auto it = p_map.getDomainIterator();
135 while (it.isNext()) {
139 p_map.getPos(key)[i] = parts.
getPos(key)[i];
142 p_map.template getProp<0>(key) = cnt + s_pnt;
149 p_map.template ghost_get<0>();
155 typename Sys_eqs::stype scal;
162 constant_b(
typename Sys_eqs::stype scal) {
175 typename Sys_eqs::stype get(
size_t key) {
181 template<
unsigned int prp_
id>
184 typename Sys_eqs::stype scal;
205 inline typename Sys_eqs::stype get(
size_t key) {
206 return parts.template getProp<prp_id>(key);
219 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__
220 <<
" the term B and the Matrix A for Ax=B must contain the same number of rows " << row <<
"!=" << row_b <<
"\n";
223 if (row_b != p_map.size_local() * Sys_eqs::nvar) {
224 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__ <<
" your system is underdetermined you set " 225 << row_b <<
" conditions " <<
" but i am expecting " << p_map.size_local() * Sys_eqs::nvar
232 nz_rows.resize(row_b);
234 for (
size_t i = 0; i < trpl.
size(); i++) {
235 if (trpl.get(i).row() - s_pnt * Sys_eqs::nvar >= nz_rows.
size()) {
236 std::cerr <<
"Error " << __FILE__ <<
":" << __LINE__
237 <<
" It seems that you are setting colums that does not exist \n";
239 if (trpl.get(i).value() != 0) { nz_rows.get(trpl.get(i).row() - s_pnt * Sys_eqs::nvar) =
true; }
248 nz_cols.resize(row_b);
250 for (
size_t i = 0; i < trpl.
size(); i++) {
251 if (trpl.get(i).value() != 0) { nz_cols.get(trpl.get(i).col()) =
true; }
255 for (
size_t i = 0; i < nz_rows.
size(); i++) {
256 if (nz_rows.get(i) ==
false) {
257 std::cerr <<
"Error: " << __FILE__ <<
":" << __LINE__ <<
" Ill posed matrix row " << i
258 <<
" is not filled " <<
" equation: " <<
"\n";
263 for (
size_t i = 0; i < nz_cols.
size(); i++) {
264 if (nz_cols.get(i) ==
false)
265 std::cerr <<
"Error: " << __FILE__ <<
":" << __LINE__ <<
" Ill posed matrix colum " << i
266 <<
" is not filled\n";
278 template<
typename solType,
typename expr_type>
279 void copy_impl(solType & x, expr_type exp,
unsigned int comp)
281 auto & parts = exp.getVector();
285 while (it.isNext()) {
287 exp.value(p) = x(p.getKey() * Sys_eqs::nvar + comp + s_pnt * Sys_eqs::nvar);
292 template<
typename solType,
typename exp1,
typename ... othersExp>
293 void copy_nested(solType &x,
unsigned int &comp, exp1 exp, othersExp ... exps) {
294 copy_impl(x, exp, comp);
297 copy_nested(x, comp, exps ...);
301 template<
typename solType,
typename exp1>
302 void copy_nested(solType &x,
unsigned int &comp, exp1 exp) {
303 copy_impl(x, exp, comp);
346 template<
typename ... expr_type>
347 void solve(expr_type ... exps) {
348 if (
sizeof...(exps) != Sys_eqs::nvar) {
349 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\ 350 dimensionality, I am expecting " << Sys_eqs::nvar <<
351 " properties " << std::endl;
353 typename Sys_eqs::solver_type solver;
355 auto x = solver.solve(getA(opt), getB(opt));
357 unsigned int comp = 0;
358 copy_nested(x, comp, exps ...);
369 template<
typename SolverType,
typename ... expr_type>
370 void solve_with_solver(SolverType &solver, expr_type ... exps) {
373 if (
sizeof...(exps) != Sys_eqs::nvar) {
374 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\ 375 dimensionality, I am expecting " << Sys_eqs::nvar <<
376 " properties " << std::endl;
379 auto x = solver.solve(getA(opt), getB(opt));
381 unsigned int comp = 0;
382 copy_nested(x, comp, exps ...);
417 template<
typename SolverType,
typename ... expr_type>
418 void solve_with_default_nullspace_solver(SolverType &solver, expr_type ... exps) {
421 if (
sizeof...(exps) != Sys_eqs::nvar) {
422 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\ 423 dimensionality, I am expecting " << Sys_eqs::nvar <<
424 " properties " << std::endl;
427 auto x = solver.with_constant_nullspace_solve(getA(opt), getB(opt));
429 unsigned int comp = 0;
430 copy_nested(x, comp, exps ...);
440 template<
typename SolverType,
typename ... expr_type>
441 void try_solve_with_solver(SolverType &solver, expr_type ... exps) {
442 if (
sizeof...(exps) != Sys_eqs::nvar) {
443 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error the number of properties you gave does not match the solution in\ 444 dimensionality, I am expecting " << Sys_eqs::nvar <<
445 " properties " << std::endl;
448 auto x = solver.try_solve(getA(opt), getB(opt));
450 unsigned int comp = 0;
451 copy_nested(x, comp, exps ...);
459 void reset(
particles_type &part, options_solver opt = options_solver::STANDARD)
467 A.getMatrixTriplets().clear();
477 A.getMatrixTriplets().clear();
487 DCPSE_scheme(
particles_type &part, options_solver opt = options_solver::STANDARD)
488 : parts(part), p_map(part.getDecomposition(), 0), row(0), row_b(0), opt(opt) {
514 template<
typename T,
typename index_type,
unsigned int prp_
id>
518 auto itd = subset.template getIteratorElements<0>();
520 variable_b<prp_id> vb(parts);
522 impose_git(op, vb,
id.getId(), itd);
535 template<
typename index_type,
unsigned int prp_
id>
539 auto itd = subset.template getIteratorElements<0>();
541 variable_b<prp_id> vb(parts);
543 impose_git_b(vb,
id.getId(), itd);
559 template<typename T, typename index_type, typename RHS_type, typename sfinae = typename std::enable_if<!std::is_fundamental<RHS_type>::type::value>::type>
563 auto itd = subset.template getIteratorElements<0>();
565 impose_git(op, rhs,
id.getId(), itd);
578 template<typename index_type, typename RHS_type, typename sfinae = typename std::enable_if<!std::is_fundamental<RHS_type>::type::value>::type>
582 auto itd = subset.template getIteratorElements<0>();
583 impose_git_b(rhs,
id.getId(), itd);
599 template<
typename T,
typename index_type>
600 void impose(
const T &op,
602 const typename Sys_eqs::stype num,
604 auto itd = subset.template getIteratorElements<0>();
608 impose_git(op, b,
id.getId(), itd);
621 template<
typename index_type>
623 const typename Sys_eqs::stype num,
625 auto itd = subset.template getIteratorElements<0>();
629 impose_git_b(b,
id.getId(), itd);
637 template<
typename options>
638 typename Sys_eqs::SparseMatrix_type &getA(options opt) {
642 if (opt == options_solver::STANDARD) {
643 A.resize(tot * Sys_eqs::nvar, tot * Sys_eqs::nvar,
644 p_map.size_local() * Sys_eqs::nvar,
645 p_map.size_local() * Sys_eqs::nvar);
647 else if (opt == options_solver::LAGRANGE_MULTIPLIER) {
648 auto &v_cl = create_vcluster();
651 if (v_cl.
rank() == v_cl.
size() - 1) {
652 A.resize(tot * Sys_eqs::nvar + 1, tot * Sys_eqs::nvar + 1,
653 p_map.size_local() * Sys_eqs::nvar + 1,
654 p_map.size_local() * Sys_eqs::nvar + 1);
656 for (
int i = 0; i < tot * Sys_eqs::nvar; i++) {
659 t1.row() = tot * Sys_eqs::nvar;
666 for (
int i = 0; i < p_map.size_local() * Sys_eqs::nvar; i++) {
669 t2.row() = i + s_pnt * Sys_eqs::nvar;
670 t2.col() = tot * Sys_eqs::nvar;
678 t3.col() = tot * Sys_eqs::nvar;
679 t3.row() = tot * Sys_eqs::nvar;
688 A.resize(tot * Sys_eqs::nvar + 1, tot * Sys_eqs::nvar + 1,
689 p_map.size_local() * Sys_eqs::nvar,
690 p_map.size_local() * Sys_eqs::nvar);
692 for (
int i = 0; i < p_map.size_local() * Sys_eqs::nvar; i++) {
695 t2.row() = i + s_pnt * Sys_eqs::nvar;
696 t2.col() = tot * Sys_eqs::nvar;
707 auto &v_cl = create_vcluster();
708 if (v_cl.
rank() == v_cl.
size() - 1) {
709 A.resize(tot * Sys_eqs::nvar - offset, tot * Sys_eqs::nvar - offset,
710 p_map.size_local() * Sys_eqs::nvar - offset,
711 p_map.size_local() * Sys_eqs::nvar - offset);
714 A.resize(tot * Sys_eqs::nvar - offset, tot * Sys_eqs::nvar - offset,
715 p_map.size_local() * Sys_eqs::nvar,
716 p_map.size_local() * Sys_eqs::nvar);
729 typename Sys_eqs::Vector_type &getB(options_solver opt = options_solver::STANDARD) {
733 if (opt == options_solver::LAGRANGE_MULTIPLIER) {
734 auto &v_cl = create_vcluster();
735 if (v_cl.
rank() == v_cl.
size() - 1) {
737 b(tot * Sys_eqs::nvar) = 0;
744 template<
typename bop,
typename iterator>
745 void impose_git_b(bop num,
747 const iterator &it_d) {
750 while (it.isNext()) {
754 b(p_map.template getProp<0>(key) * Sys_eqs::nvar +
id) = num.get(key);
781 template<
typename T,
typename bop,
typename iterator>
782 void impose_git(
const T &op,
785 const iterator &it_d) {
795 while (it.isNext()) {
808 typename Sys_eqs::stype coeff = 1.0;
809 op.template value_nz<Sys_eqs>(p_map, key, cols, coeff, 0);
812 bool is_diag =
false;
815 for (
auto it = cols.begin(); it != cols.end(); ++it) {
817 trpl.last().row() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
818 trpl.last().col() = it->first;
819 trpl.last().value() = it->second;
820 if (trpl.last().row() == trpl.last().col())
825 if (is_diag ==
false)
828 trpl.last().row() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
829 trpl.last().col() = p_map.template getProp<0>(key) * Sys_eqs::nvar + id;
830 trpl.last().value() = 0.0;
832 b(p_map.template getProp<0>(key) * Sys_eqs::nvar +
id) = num.get(key);
848 #include "DCPSE/DCPSE_op/EqnsStruct.hpp" 850 #endif //OPENFPM_PDATA_DCPSE_SOLVER_HPP size_t getProcessUnitID()
Get the process unit id.
It store the non zero elements of the matrix.
bool allGather(T &send, openfpm::vector< T, Mem, gr > &v)
Gather the data from all processors.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
Implementation of VCluster class.
void resize(size_t rs)
Resize the vector (locally)
void execute()
Execute all the requests.
It model an expression expr1 * expr2.
size_t size_local() const
return the local size of the vector
size_t rank()
Get the process unit id.
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.
size_t getProcessingUnits()
Get the total number of processors.
static const unsigned int dims
dimensions of space
void sum(T &num)
Sum the numbers across all processors and get the result.
size_t size()
Get the total number of processors.
vect_dist_key_dx get()
Get the actual key.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.