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_ns_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 //
12 //
13 
14 #if !defined(KRATOS_AMGCL_NAVIERSTOKES_SOLVER )
15 #define KRATOS_AMGCL_NAVIERSTOKES_SOLVER
16 
17 #ifndef AMGCL_PARAM_UNKNOWN
18 #include "input_output/logger.h"
19 # define AMGCL_PARAM_UNKNOWN(name) \
20  Kratos::Logger("AMGCL") << KRATOS_CODE_LOCATION << Kratos::Logger::Severity::WARNING << "Unknown parameter " << name << std::endl
21 #endif
22 
23 // External includes
24 #include <iostream>
25 #include <utility>
26 
28 
29 // Project includes
30 #include "includes/define.h"
33 
34 #include <boost/property_tree/json_parser.hpp>
35 
36 #include <amgcl/adapter/crs_tuple.hpp>
37 #include <amgcl/adapter/ublas.hpp>
38 #include <amgcl/adapter/zero_copy.hpp>
39 #include <amgcl/backend/builtin.hpp>
40 #include <amgcl/value_type/static_matrix.hpp>
41 #include <amgcl/make_solver.hpp>
42 #include <amgcl/make_block_solver.hpp>
43 #include <amgcl/solver/runtime.hpp>
44 #include <amgcl/preconditioner/schur_pressure_correction.hpp>
45 #include <amgcl/preconditioner/runtime.hpp>
46 
47 namespace Kratos
48 {
49 
50 
51 template< class TSparseSpaceType, class TDenseSpaceType,
52  class TReordererType = Reorderer<TSparseSpaceType, TDenseSpaceType> >
53 class AMGCL_NS_Solver : public LinearSolver< TSparseSpaceType,
54  TDenseSpaceType, TReordererType>
55 {
56 public:
62 
64 
66 
68 
70  {
71 
72  Parameters default_parameters( R"(
73  {
74  "solver_type" : "amgcl_ns",
75  "verbosity" : 1,
76  "scaling": false,
77  "schur_variable" : "PRESSURE",
78  "inner_settings" : {
79  "solver": {
80  "type": "lgmres",
81  "M": 50,
82  "maxiter": 1000,
83  "tol": 1e-8,
84  "verbose": true
85  },
86  "precond": {
87  "pmask_size": -1,
88  "adjust_p": 0,
89  "type": 2,
90  "usolver": {
91  "solver": {
92  "type": "preonly"
93  },
94  "precond": {
95  "relax": {
96  "type": "ilup"
97  },
98  "coarsening": {
99  "type": "aggregation",
100  "aggr": {
101  "eps_strong": 0
102  }
103  }
104  }
105  },
106  "psolver": {
107  "solver": {
108  "type": "preonly"
109  }
110  }
111  }
112  }
113  } )" );
114 
115 
116  //now validate agains defaults -- this also ensures no type mismatch
117  rParameters.ValidateAndAssignDefaults(default_parameters);
118 
119  //kratos specific settings
120  mTol = rParameters["inner_settings"]["solver"]["tol"].GetDouble();
121  mVerbosity=rParameters["verbosity"].GetInt();
122  const std::string pressure_var_name = rParameters["schur_variable"].GetString();
123  mpPressureVar = &KratosComponents<Variable<double>>::Get(pressure_var_name);
124  mndof = 1;
125 
126  //pass settings to amgcl
127  std::stringstream inner_settings;
128  inner_settings << rParameters["inner_settings"].PrettyPrintJsonString() << std::endl;
129  //KRATOS_WATCH(inner_settings)
130  boost::property_tree::read_json(inner_settings, mprm);
131 
132  }
133 
137  ~AMGCL_NS_Solver() override {};
138 
147  bool Solve(SparseMatrixType& rA, VectorType& rX, VectorType& rB) override
148  {
149 
150  mprm.put("precond.pmask", static_cast<void*>(&mp[0]));
151  mprm.put("precond.pmask_size", mp.size());
152  mprm.put("solver.verbose", mVerbosity > 1);
153 
154  if(mVerbosity > 1)
155  write_json(std::cout, mprm);
156 
157  if(mVerbosity == 4)
158  {
159  //output to matrix market
160  std::stringstream matrix_market_name;
161  matrix_market_name << "A" << ".mm";
162  TSparseSpaceType::WriteMatrixMarketMatrix((char*) (matrix_market_name.str()).c_str(), rA, false);
163 
164  std::stringstream matrix_market_vectname;
165  matrix_market_vectname << "b" << ".mm.rhs";
166  TSparseSpaceType::WriteMatrixMarketVector((char*) (matrix_market_vectname.str()).c_str(), rB);
167 
168  KRATOS_THROW_ERROR(std::logic_error, "verbosity = 4 prints the matrix and exits","")
169  }
170 
171  size_t iters;
172  double resid;
173 
174  switch (mndof)
175  {
176  case 3:
177  std::tie(iters, resid) = block_solve<2>(rA, rX, rB);
178  break;
179  case 4:
180  std::tie(iters, resid) = block_solve<3>(rA, rX, rB);
181  break;
182  default:
183  std::tie(iters, resid) = scalar_solve(rA, rX, rB);
184  }
185 
186  KRATOS_WARNING_IF("AMGCL NS Linear Solver", mTol < resid)
187  << "Non converged linear solution. " << resid << std::endl;
188 
189  if(mVerbosity > 1)
190  {
191  std::cout << "Iterations: " << iters << std::endl
192  << "Error: " << resid << std::endl
193  << std::endl;
194  }
195 
196  bool is_solved = true;
197  if(resid > mTol)
198  is_solved = false;
199 
200  return is_solved;
201  }
202 
203  std::tuple<size_t, double> scalar_solve(SparseMatrixType& rA, VectorType& rX, VectorType& rB) const
204  {
205  typedef amgcl::backend::builtin<double> sBackend;
206  typedef amgcl::backend::builtin<float> pBackend;
207 
208  typedef amgcl::make_solver<
209  amgcl::runtime::preconditioner<pBackend>,
210  amgcl::runtime::solver::wrapper<pBackend>
211  > USolver;
212 
213  typedef amgcl::make_solver<
214  amgcl::runtime::preconditioner<pBackend>,
215  amgcl::runtime::solver::wrapper<pBackend>
216  > PSolver;
217 
218  typedef amgcl::make_solver<
219  amgcl::preconditioner::schur_pressure_correction<USolver, PSolver>,
220  amgcl::runtime::solver::wrapper<sBackend>
221  > Solver;
222 
223  auto pA = amgcl::adapter::zero_copy(
224  rA.size1(),
225  rA.index1_data().begin(),
226  rA.index2_data().begin(),
227  rA.value_data().begin()
228  );
229 
230  Solver solve(*pA, mprm);
231  KRATOS_INFO_IF("AMGCL NS Solver", mVerbosity > 1) << "AMGCL-NS Memory Occupation : " << amgcl::human_readable_memory(amgcl::backend::bytes(solve)) << std::endl;
232  return solve(*pA, rB, rX);
233  }
234 
235  template <int UBlockSize>
236  std::tuple<size_t, double> block_solve(SparseMatrixType& rA, VectorType& rX, VectorType& rB) const
237  {
238  typedef amgcl::static_matrix<float,UBlockSize,UBlockSize> fblock;
239 
240  typedef amgcl::backend::builtin<double> sBackend;
241  typedef amgcl::backend::builtin<fblock> uBackend;
242  typedef amgcl::backend::builtin<float> pBackend;
243 
244  typedef amgcl::make_block_solver<
245  amgcl::runtime::preconditioner<uBackend>,
246  amgcl::runtime::solver::wrapper<uBackend>
247  > USolver;
248 
249  typedef amgcl::make_solver<
250  amgcl::runtime::preconditioner<pBackend>,
251  amgcl::runtime::solver::wrapper<pBackend>
252  > PSolver;
253 
254  typedef amgcl::make_solver<
255  amgcl::preconditioner::schur_pressure_correction<USolver, PSolver>,
256  amgcl::runtime::solver::wrapper<sBackend>
257  > Solver;
258 
259  auto pA = amgcl::adapter::zero_copy(
260  rA.size1(),
261  rA.index1_data().begin(),
262  rA.index2_data().begin(),
263  rA.value_data().begin()
264  );
265 
266  Solver solve(*pA, mprm);
267  KRATOS_INFO_IF("AMGCL NS Solver", mVerbosity > 1) << "AMGCL-NS Memory Occupation : " << amgcl::human_readable_memory(amgcl::backend::bytes(solve)) << std::endl;
268  return solve(*pA, rB, rX);
269  }
270 
280  {
281  return false;
282 
283  }
284 
288  void PrintInfo(std::ostream& rOStream) const override
289  {
290  rOStream << "AMGCL NS Solver finished.";
291  }
292 
296  void PrintData(std::ostream& rOStream) const override
297  {
298  }
299 
307  {
308  return true;
309  }
310 
318  SparseMatrixType& rA,
319  VectorType& rX,
320  VectorType& rB,
321  typename ModelPart::DofsArrayType& rDofSet,
322  ModelPart& rModelPart
323  ) override
324  {
325  //*****************************
326  //compute block size
327  int old_ndof = -1;
328  int ndof=0;
329  if (!rModelPart.IsDistributed())
330  {
331  unsigned int old_node_id = rDofSet.size() ? rDofSet.begin()->Id() : 0;
332  for (auto it = rDofSet.begin(); it!=rDofSet.end(); it++) {
333  if(it->EquationId() < TSparseSpaceType::Size1(rA) ) {
334  IndexType id = it->Id();
335  if(id != old_node_id) {
336  old_node_id = id;
337  if(old_ndof == -1) old_ndof = ndof;
338  else if(old_ndof != ndof) { //if it is different than the block size is 1
339  old_ndof = -1;
340  break;
341  }
342 
343  ndof=1;
344  } else {
345  ndof++;
346  }
347  }
348  }
349 
350  if(old_ndof == -1)
351  mndof = 1;
352  else
353  mndof = ndof;
354 
355  }
356  else //distribute
357  {
358  const std::size_t system_size = TSparseSpaceType::Size1(rA);
359  int current_rank = rModelPart.GetCommunicator().GetDataCommunicator().Rank();
360  unsigned int old_node_id = rDofSet.size() ? rDofSet.begin()->Id() : 0;
361  for (auto it = rDofSet.begin(); it!=rDofSet.end(); it++) {
362  if(it->EquationId() < system_size && it->GetSolutionStepValue(PARTITION_INDEX) == current_rank) {
363  IndexType id = it->Id();
364  if(id != old_node_id) {
365  old_node_id = id;
366  if(old_ndof == -1) old_ndof = ndof;
367  else if(old_ndof != ndof) { //if it is different than the block size is 1
368  old_ndof = -1;
369  break;
370  }
371 
372  ndof=1;
373  } else {
374  ndof++;
375  }
376  }
377  }
378 
379  if(old_ndof != -1)
380  mndof = ndof;
381 
382  int max_block_size = rModelPart.GetCommunicator().GetDataCommunicator().MaxAll(mndof);
383 
384  if( old_ndof == -1) {
385  mndof = max_block_size;
386  }
387 
388  KRATOS_ERROR_IF(mndof != max_block_size) << "Block size is not consistent. Local: " << mndof << " Max: " << max_block_size << std::endl;
389  }
390 
391  KRATOS_INFO_IF("AMGCL NS Solver", mVerbosity > 1) << "mndof: " << mndof << std::endl;
392 
393  // if(mProvideCoordinates) {
394  // mCoordinates.resize(TSparseSpaceType::Size1(rA)/mndof);
395  // unsigned int i=0;
396  // for (auto it_dof = rDofSet.begin(); it_dof!=rDofSet.end(); it_dof+=mndof) {
397  // if(it_dof->EquationId() < TSparseSpaceType::Size1(rA) ) {
398  // auto it_node = rModelPart.Nodes().find(it_dof->Id());
399  // mCoordinates[ i ] = it_node->Coordinates();
400  // i++;
401  // }
402  // }
403  // }
404 
405 
406  //*****************************
407  //compute pressure mask
408  if(mp.size() != rA.size1()) mp.resize( rA.size1() );
409  for (ModelPart::DofsArrayType::iterator it = rDofSet.begin(); it!=rDofSet.end(); it++)
410  {
411  const unsigned int eq_id = it->EquationId();
412  if( eq_id < rA.size1() )
413  {
414  mp[eq_id] = (it->GetVariable().Key() == *mpPressureVar);
415  }
416  }
417 
418 
419  }
420 
421 private:
422 
423  double mTol;
424  int mVerbosity;
425  const Variable<double>* mpPressureVar = nullptr;
426  int mndof;
427  std::vector< char > mp;
428 
429  boost::property_tree::ptree mprm;
430 
434  AMGCL_NS_Solver& operator=(const AMGCL_NS_Solver& Other);
435 
439  AMGCL_NS_Solver(const AMGCL_NS_Solver& Other);
440 
441 }; // Class AMGCL_NS_Solver
442 
443 
447 template<class TSparseSpaceType, class TDenseSpaceType,class TReordererType>
448 inline std::istream& operator >> (std::istream& rIStream, AMGCL_NS_Solver< TSparseSpaceType,
449  TDenseSpaceType, TReordererType>& rThis)
450 {
451  return rIStream;
452 }
453 
457 template<class TSparseSpaceType, class TDenseSpaceType, class TReordererType>
458 inline std::ostream& operator << (std::ostream& rOStream,
459  const AMGCL_NS_Solver<TSparseSpaceType,
460  TDenseSpaceType, TReordererType>& rThis)
461 {
462  rThis.PrintInfo(rOStream);
463  rOStream << std::endl;
464  rThis.PrintData(rOStream);
465 
466  return rOStream;
467 }
468 
469 } // namespace Kratos.
470 
471 
472 
473 #endif // KRATOS_AMGCL_NAVIERSTOKES_SOLVER defined
Definition: amgcl_ns_solver.h:55
TSparseSpaceType::MatrixType SparseMatrixType
Definition: amgcl_ns_solver.h:63
std::tuple< size_t, double > scalar_solve(SparseMatrixType &rA, VectorType &rX, VectorType &rB) const
Definition: amgcl_ns_solver.h:203
void PrintData(std::ostream &rOStream) const override
Definition: amgcl_ns_solver.h:296
TDenseSpaceType::MatrixType DenseMatrixType
Definition: amgcl_ns_solver.h:67
bool Solve(SparseMatrixType &rA, DenseMatrixType &rX, DenseMatrixType &rB) override
Definition: amgcl_ns_solver.h:279
std::tuple< size_t, double > block_solve(SparseMatrixType &rA, VectorType &rX, VectorType &rB) const
Definition: amgcl_ns_solver.h:236
TSparseSpaceType::VectorType VectorType
Definition: amgcl_ns_solver.h:65
void PrintInfo(std::ostream &rOStream) const override
Definition: amgcl_ns_solver.h:288
void ProvideAdditionalData(SparseMatrixType &rA, VectorType &rX, VectorType &rB, typename ModelPart::DofsArrayType &rDofSet, ModelPart &rModelPart) override
Definition: amgcl_ns_solver.h:317
~AMGCL_NS_Solver() override
Definition: amgcl_ns_solver.h:137
KRATOS_CLASS_POINTER_DEFINITION(AMGCL_NS_Solver)
bool Solve(SparseMatrixType &rA, VectorType &rX, VectorType &rB) override
Definition: amgcl_ns_solver.h:147
LinearSolver< TSparseSpaceType, TDenseSpaceType, TReordererType > BaseType
Definition: amgcl_ns_solver.h:61
AMGCL_NS_Solver(Parameters rParameters)
Definition: amgcl_ns_solver.h:69
bool AdditionalPhysicalDataIsNeeded() override
Definition: amgcl_ns_solver.h:306
virtual const DataCommunicator & GetDataCommunicator() const
Definition: communicator.cpp:340
virtual int Rank() const
Get the parallel rank for this DataCommunicator.
Definition: data_communicator.h:587
KratosComponents class encapsulates a lookup table for a family of classes in a generic way.
Definition: kratos_components.h:49
Base class for all the linear solvers in Kratos.
Definition: linear_solver.h:65
TSparseSpaceType::IndexType IndexType
The index type definition to be consistent.
Definition: linear_solver.h:88
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
Communicator & GetCommunicator()
Definition: model_part.h:1821
bool IsDistributed() const
Definition: model_part.h:1898
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
const std::string PrettyPrintJsonString() const
This method returns a string with the corresponding text to the equivalent *.json file (this version ...
Definition: kratos_parameters.cpp:415
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
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
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_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_INFO_IF(label, conditional)
Definition: logger.h:251
#define KRATOS_WARNING_IF(label, conditional)
Definition: logger.h:266
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
TSpaceType::IndexType Size1(TSpaceType &dummy, typename TSpaceType::MatrixType const &rM)
Definition: add_strategies_to_python.cpp:117
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
bool WriteMatrixMarketVector(const char *FileName, VectorType &V)
Definition: matrix_market_interface.h:539
bool WriteMatrixMarketMatrix(const char *FileName, CompressedMatrixType &M, bool Symmetric)
Definition: matrix_market_interface.h:308
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
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