KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
amgcl_mpi_schur_complement_solver.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Denis Demidov
11 // Riccardo Rossi
12 //
13 
14 #if !defined (KRATOS_AMGCL_MPI_SCHUR_COMPLEMENT_SOLVER_H_INCLUDED)
15 #define KRATOS_AMGCL_MPI_SCHUR_COMPLEMENT_SOLVER_H_INCLUDED
16 
17 
18 #ifndef AMGCL_PARAM_UNKNOWN
19 #include "input_output/logger.h"
20 # define AMGCL_PARAM_UNKNOWN(name) \
21  Kratos::Logger("AMGCL") << KRATOS_CODE_LOCATION << Kratos::Logger::Severity::WARNING << "Unknown parameter " << name << std::endl
22 #endif
23 
24 // External includes
25 
26 // Project includes
27 #include "includes/define.h"
32 
33 #include <boost/range/iterator_range.hpp>
34 #include <boost/property_tree/json_parser.hpp>
35 
36 #include <amgcl/amg.hpp>
37 #include <amgcl/adapter/epetra.hpp>
38 
39 #include <amgcl/mpi/make_solver.hpp>
40 #include <amgcl/mpi/schur_pressure_correction.hpp>
41 #include <amgcl/mpi/solver/runtime.hpp>
42 #include <amgcl/mpi/block_preconditioner.hpp>
43 #include <amgcl/relaxation/as_preconditioner.hpp>
44 #include <amgcl/relaxation/runtime.hpp>
45 #include <amgcl/mpi/amg.hpp>
46 #include <amgcl/mpi/coarsening/runtime.hpp>
47 #include <amgcl/mpi/relaxation/runtime.hpp>
48 #include <amgcl/mpi/direct_solver/runtime.hpp>
49 #include <amgcl/mpi/partition/runtime.hpp>
50 
51 namespace Kratos
52 {
53 
54 template< class TSparseSpaceType, class TDenseSpaceType,
55  class TReordererType = Reorderer<TSparseSpaceType, TDenseSpaceType> >
56 class AmgclMPISchurComplementSolver : public LinearSolver< TSparseSpaceType,
57  TDenseSpaceType, TReordererType>
58 {
59 public:
64 
66 
68 
70 
72 
73 
75  {
76  Parameters default_parameters( R"(
77  {
78  "solver_type" : "AmgclMPISchurComplementSolver",
79  "krylov_type" : "fgmres",
80  "velocity_block_preconditioner" :
81  {
82  "krylov_type" : "lgmres",
83  "tolerance" : 1e-3,
84  "preconditioner_type" : "ilu0",
85  "max_iteration": 5
86  },
87  "pressure_block_preconditioner" :
88  {
89  "krylov_type" : "fgmres",
90  "tolerance" : 1e-2,
91  "preconditioner_type" : "spai0",
92  "max_iteration": 20
93  },
94  "tolerance" : 1e-9,
95  "gmres_krylov_space_dimension": 50,
96  "coarsening_type": "aggregation",
97  "max_iteration": 50,
98  "verbosity" : 1,
99  "scaling": false,
100  "coarse_enough" : 5000
101  } )" );
102 
103 
104  //now validate agains defaults -- this also ensures no type mismatch
105  rParameters.ValidateAndAssignDefaults(default_parameters);
106 
107  std::stringstream msg;
108 
109  //validate if values are admissible
110  std::set<std::string> available_preconditioners = {"spai0","ilu0","damped_jacobi","gauss_seidel","chebyshev"};
111 
112  //check velocity block settings
113  if(available_preconditioners.find(rParameters["velocity_block_preconditioner"]["preconditioner_type"].GetString()) == available_preconditioners.end())
114  {
115  msg << "currently prescribed velocity_block_preconditioner preconditioner_type : " << rParameters["velocity_block_preconditioner"]["smoother_type"].GetString() << std::endl;
116  msg << "admissible values are : spai0,ilu0,damped_jacobi,gauss_seidel,chebyshev"<< std::endl;
117  KRATOS_THROW_ERROR(std::invalid_argument," smoother_type is invalid: ",msg.str());
118  }
119 
120  mCoarseEnough = rParameters["coarse_enough"].GetInt();
121 
122 // {
123 // "solver": {
124 // "type" : "fgmres",
125 // "M": 50
126 // },
127 // "precond": {
128 // "usolver": {
129 // "solver": {
130 // "type" : "gmres",
131 // "tol": 0.001,
132 // "maxiter": 5
133 // }
134 // },
135 // "psolver": {
136 // "solver": {
137 // "type" : "gmres",
138 // "tol": 0.01,
139 // "maxiter": 20
140 // },
141 // "precond" : {
142 // "isolver" : {
143 // "type" : "gmres",
144 // "maxiter" : 2
145 // }
146 // }
147 // }
148 // }
149 // }
150 
151  mTolerance = rParameters["tolerance"].GetDouble();
152  mMaxIterations = rParameters["max_iteration"].GetInt();
153  mVerbosity=rParameters["verbosity"].GetInt();
154  mprm.put("solver.type", rParameters["krylov_type"].GetString());
155 
156  if(rParameters["krylov_type"].GetString() == "gmres" || rParameters["krylov_type"].GetString() == "lgmres" || rParameters["krylov_type"].GetString() == "fgmres")
157  mprm.put("solver.M", rParameters["gmres_krylov_space_dimension"].GetInt());
158 
159  //setting velocity solver options
160  mprm.put("precond.usolver.solver.type", rParameters["velocity_block_preconditioner"]["krylov_type"].GetString());
161  mprm.put("precond.usolver.solver.tol", rParameters["velocity_block_preconditioner"]["tolerance"].GetDouble());
162  mprm.put("precond.usolver.solver.maxiter", rParameters["velocity_block_preconditioner"]["max_iteration"].GetInt());
163  mprm.put("precond.usolver.precond.type", rParameters["velocity_block_preconditioner"]["preconditioner_type"].GetString());
164 
165  //setting pressure solver options
166  mprm.put("precond.psolver.solver.type", rParameters["pressure_block_preconditioner"]["krylov_type"].GetString());
167  mprm.put("precond.psolver.solver.tol", rParameters["pressure_block_preconditioner"]["tolerance"].GetDouble());
168  mprm.put("precond.psolver.solver.maxiter", rParameters["pressure_block_preconditioner"]["max_iteration"].GetInt());
169  mprm.put("precond.psolver.precond.relax.type", rParameters["pressure_block_preconditioner"]["preconditioner_type"].GetString());
170  mprm.put("precond.psolver.precond.coarse_enough", mCoarseEnough);
171 // mprm.put("precond.psolver.precond.local.coarsening.aggr.eps_strong", 0.0);
172 // mprm.put("precond.psolver.precond.local.coarsening.aggr.block_size", 1);
173 
174  }
175 
176 
181 
190  bool Solve ( SparseMatrixType& rA, VectorType& rX, VectorType& rB ) override
191  {
192  KRATOS_TRY
193 
194  //using amgcl::prof;
195  //prof.reset();
196 
197  MPI_Comm the_comm = TrilinosSolverUtilities::GetMPICommFromEpetraComm(rA.Comm());
198 
199  amgcl::mpi::communicator world ( the_comm );
200  if ( mVerbosity >=0 && world.rank == 0 ) {
201  std::cout << "World size: " << world.size << std::endl;
202  }
203 
204  int chunk = rA.NumMyRows();
205  boost::iterator_range<double*> xrange ( rX.Values(), rX.Values() + chunk );
206  boost::iterator_range<double*> frange ( rB.Values(), rB.Values() + chunk );
207 
208  if ( mVerbosity > 1 && world.rank == 0 ) {
209  write_json ( std::cout, mprm );
210  }
211 
212  typedef amgcl::backend::builtin<double> Backend;
213 
214  typedef amgcl::mpi::make_solver<
215  amgcl::mpi::schur_pressure_correction<
216  amgcl::mpi::make_solver<
217  amgcl::mpi::block_preconditioner<
218  amgcl::relaxation::as_preconditioner<Backend, amgcl::runtime::relaxation::wrapper>
219  >,
220  amgcl::runtime::mpi::solver::wrapper<Backend>
221  >,
222  amgcl::mpi::make_solver<
223  amgcl::mpi::amg<
224  Backend,
225  amgcl::runtime::mpi::coarsening::wrapper<Backend>,
226  amgcl::runtime::mpi::relaxation::wrapper<Backend>,
227  amgcl::runtime::mpi::direct::solver<double>,
228  amgcl::runtime::mpi::partition::wrapper<Backend>
229  >,
230  amgcl::runtime::mpi::solver::wrapper<Backend>
231  >
232  >,
233  amgcl::runtime::mpi::solver::wrapper<Backend>
234  > Solver;
235 
236  mprm.put("precond.pmask", static_cast<void*>(&mPressureMask[0]));
237  mprm.put("precond.pmask_size", mPressureMask.size());
238 
239  //prof.tic ( "setup" );
240  Solver solve ( world, amgcl::adapter::map ( rA ), mprm );
241  //double tm_setup = prof.toc ( "setup" );
242 
243  //prof.tic ( "Solve" );
244  size_t iters;
245  double resid;
246  std::tie ( iters, resid ) = solve ( frange, xrange );
247  //double solve_tm = prof.toc ( "Solve" );
248 
249 
250 
251  if ( rA.Comm().MyPID() == 0 ) {
252  if ( mVerbosity > 0 ) {
253  std::cout
254  << "------- AMGCL -------\n" << std::endl
255  << "Iterations : " << iters << std::endl
256  << "Error : " << resid << std::endl;
257  //<< "amgcl setup time: " << tm_setup << std::endl
258  //<< "amgcl solve time: " << solve_tm << std::endl;
259  }
260 
261  // if ( mVerbosity > 1 ) {
262  // std::cout << prof << std::endl;
263  // }
264  }
265 
266 
267 
268  return true;
269 
270  KRATOS_CATCH ( "" );
271  }
272 
277 
282 
291  bool Solve ( SparseMatrixType& rA, DenseMatrixType& rX, DenseMatrixType& rB ) override
292  {
293  return false;
294  }
295 
303  {
304  return true;
305  }
306 
314  SparseMatrixType& rA,
315  VectorType& rX,
316  VectorType& rB,
317  typename ModelPart::DofsArrayType& rDofSet,
318  ModelPart& rModelPart
319  ) override
320  {
321 
322  int my_pid = rA.Comm().MyPID();
323 
324  //filling the pressure mask
325  if(mPressureMask.size() != static_cast<unsigned int>(rA.NumMyRows()))
326  mPressureMask.resize( rA.NumMyRows(), false );
327 
328  int counter = 0;
329 #ifdef KRATOS_DEBUG
330  int npressures = 0;
331 #endif
332  for (ModelPart::DofsArrayType::iterator it = rDofSet.begin(); it!=rDofSet.end(); it++)
333  {
334  if( it->GetSolutionStepValue ( PARTITION_INDEX ) == my_pid )
335  {
336  mPressureMask[counter] = (it->GetVariable().Key() == PRESSURE);
337  counter++;
338 
339 #ifdef KRATOS_DEBUG
340  if(it->GetVariable().Key() == PRESSURE)
341  npressures++;
342 #endif
343  }
344  }
345 #ifdef KRATOS_DEBUG
346  std::cout << "MPI proc :" << my_pid << " npressures = " << npressures << " local rows = " << rA.NumMyRows();
347 #endif
348  if(counter != rA.NumMyRows())
349  KRATOS_ERROR << "pressure mask as a size " << mPressureMask.size() << " which does not correspond with the number of local rows:" << rA.NumMyRows() << std::endl;
350 
351  }
352 
354  void PrintInfo ( std::ostream& rOStream ) const override
355  {
356  rOStream << "AMGCL-MPI-Schur-Complement-Solver";
357  }
358 
359 private:
360 
361  double mTolerance;
362  int mMaxIterations;
363  int mVerbosity = 0;
364  unsigned int mCoarseEnough = 5000;
365 
366  std::vector< char > mPressureMask; //pressure mask
367  boost::property_tree::ptree mprm;
368 };
369 
371 template<class TSparseSpaceType, class TDenseSpaceType, class TReordererType>
372 inline std::ostream& operator << ( std::ostream& rOStream,
373  const AmgclMPISchurComplementSolver<TSparseSpaceType,
374  TDenseSpaceType, TReordererType>& rThis )
375 {
376  rThis.PrintInfo ( rOStream );
377  rOStream << std::endl;
378  rThis.PrintData ( rOStream );
379 
380  return rOStream;
381 }
382 
383 } // namespace Kratos.
384 
385 #endif // KRATOS_AMGCL_MPI_SCHUR_COMPLEMENT_SOLVER_H_INCLUDED defined
Definition: amgcl_mpi_schur_complement_solver.h:58
LinearSolver< TSparseSpaceType, TDenseSpaceType, TReordererType > BaseType
Definition: amgcl_mpi_schur_complement_solver.h:65
bool Solve(SparseMatrixType &rA, VectorType &rX, VectorType &rB) override
Definition: amgcl_mpi_schur_complement_solver.h:190
void ProvideAdditionalData(SparseMatrixType &rA, VectorType &rX, VectorType &rB, typename ModelPart::DofsArrayType &rDofSet, ModelPart &rModelPart) override
Definition: amgcl_mpi_schur_complement_solver.h:313
bool Solve(SparseMatrixType &rA, DenseMatrixType &rX, DenseMatrixType &rB) override
Definition: amgcl_mpi_schur_complement_solver.h:291
TSparseSpaceType::MatrixType SparseMatrixType
Definition: amgcl_mpi_schur_complement_solver.h:67
bool AdditionalPhysicalDataIsNeeded() override
Definition: amgcl_mpi_schur_complement_solver.h:302
virtual ~AmgclMPISchurComplementSolver()
Definition: amgcl_mpi_schur_complement_solver.h:180
TSparseSpaceType::VectorType VectorType
Definition: amgcl_mpi_schur_complement_solver.h:69
AmgclMPISchurComplementSolver(Parameters rParameters)
Definition: amgcl_mpi_schur_complement_solver.h:74
TDenseSpaceType::MatrixType DenseMatrixType
Definition: amgcl_mpi_schur_complement_solver.h:71
AmgclMPISchurComplementSolver & operator=(const AmgclMPISchurComplementSolver &Other)=delete
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: amgcl_mpi_schur_complement_solver.h:354
KRATOS_CLASS_POINTER_DEFINITION(AmgclMPISchurComplementSolver)
AmgclMPISchurComplementSolver(const AmgclMPISchurComplementSolver &Other)=delete
Base class for all the linear solvers in Kratos.
Definition: linear_solver.h:65
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
double GetDouble() const
This method returns the double contained in the current Parameter.
Definition: kratos_parameters.cpp:657
int GetInt() const
This method returns the integer contained in the current Parameter.
Definition: kratos_parameters.cpp:666
void ValidateAndAssignDefaults(const Parameters &rDefaultParameters)
This function is designed to verify that the parameters under testing match the form prescribed by th...
Definition: kratos_parameters.cpp:1306
std::string GetString() const
This method returns the string contained in the current Parameter.
Definition: kratos_parameters.cpp:684
A sorted associative container similar to an STL set, but uses a vector to store pointers to its data...
Definition: pointer_vector_set.h:72
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: pointer_vector_set.h:95
iterator begin()
Returns an iterator pointing to the beginning of the container.
Definition: pointer_vector_set.h:278
iterator end()
Returns an iterator pointing to the end of the container.
Definition: pointer_vector_set.h:314
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
MPI_Comm GetMPICommFromEpetraComm(const Epetra_Comm &rEpetraComm)
Definition: trilinos_solver_utilities.cpp:32
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
def solve(A, rhs)
Definition: ode_solve.py:303
int counter
Definition: script_THERMAL_CORRECT.py:218