HermesCommon  3.0
paralution_solver.cpp
Go to the documentation of this file.
1 // This file is part of HermesCommon
2 //
3 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
4 // Email: hpfem-group@unr.edu, home page: http://www.hpfem.org/.
5 //
6 // Hermes is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the License,
9 // or (at your option) any later version.
10 //
11 // Hermes is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Hermes; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "config.h"
23 #ifdef WITH_PARALUTION
24 #include "paralution_solver.h"
25 #include "util/memory_handling.h"
26 
27 namespace Hermes
28 {
29  namespace Algebra
30  {
31  template<typename Scalar>
33  : CSRMatrix<Scalar>(), paralutionMatrixType(type)
34  {
35  }
36 
37  template<typename Scalar>
39  {
40  this->paralutionMatrix.Clear();
41  this->Ap = nullptr;
42  this->Ai = nullptr;
43  this->Ax = nullptr;
44  }
45 
46  template<typename Scalar>
48  {
49  this->paralutionMatrix.Clear();
50  this->Ap = nullptr;
51  this->Ai = nullptr;
52  this->Ax = nullptr;
54  }
55 
56  template<typename Scalar>
58  {
60  }
61 
62  template<typename Scalar>
63  paralution::LocalMatrix<Scalar>& ParalutionMatrix<Scalar>::get_paralutionMatrix()
64  {
65  return this->paralutionMatrix;
66  }
67 
68  template<typename Scalar>
70  {
72  this->paralutionMatrix.SetDataPtrCSR(&this->Ap, &this->Ai, &this->Ax, "paralutionMatrix", this->nnz, this->size, this->size);
73  }
74 
75  template<typename Scalar>
76  ParalutionVector<Scalar>::ParalutionVector() : SimpleVector<Scalar>(), paralutionVector(new paralution::LocalVector<Scalar>)
77  {
78  }
79 
80  template<typename Scalar>
81  ParalutionVector<Scalar>::ParalutionVector(unsigned int size) : SimpleVector<Scalar>(size), paralutionVector(new paralution::LocalVector<Scalar>)
82  {
83  this->alloc(size);
84  this->paralutionVector->SetDataPtr(&this->v, "paralutionVector", this->size);
85  }
86 
87  template<typename Scalar>
88  void ParalutionVector<Scalar>::alloc(unsigned int n)
89  {
91  this->paralutionVector->Clear();
92  this->paralutionVector->SetDataPtr(&this->v, "vector", this->size);
93  }
94 
95  template<typename Scalar>
97  {
98  free();
99  /*
100  Temporarily suspended - introduced a memory leak
101  Reason: heap corruption upon/after execution in Agros.
102  Temporarily suspended - so far attempts to replicate in Hermes failed.
103  */
104  // delete this->paralutionVector;
105  }
106 
107  template<typename Scalar>
109  {
110  this->paralutionVector->Clear();
111  this->v = nullptr;
113  }
114 
115  template<typename Scalar>
116  paralution::LocalVector<Scalar>* ParalutionVector<Scalar>::get_paralutionVector()
117  {
118  return this->paralutionVector;
119  }
120 
121  template<typename Scalar>
123  {
124  memset(this->v, 0, this->size * sizeof(Scalar));
125  }
126 
127  template class HERMES_API ParalutionMatrix < double > ;
128  template class HERMES_API ParalutionVector < double > ;
129  }
130  namespace Solvers
131  {
132  template<typename Scalar>
133  AbstractParalutionLinearMatrixSolver<Scalar>::AbstractParalutionLinearMatrixSolver() : LoopSolver<Scalar>(nullptr, nullptr), matrix(nullptr), rhs(nullptr), paralutionSolver(nullptr)
134  {
135  this->set_max_iters(1000);
136  this->set_tolerance(1e-8, AbsoluteTolerance);
137  }
138 
139  template<typename Scalar>
140  AbstractParalutionLinearMatrixSolver<Scalar>::AbstractParalutionLinearMatrixSolver(ParalutionMatrix<Scalar> *matrix, ParalutionVector<Scalar> *rhs) : LoopSolver<Scalar>(matrix, rhs), matrix(matrix), rhs(rhs), paralutionSolver(nullptr)
141  {
142  this->set_max_iters(1000);
143  this->set_tolerance(1e-8, AbsoluteTolerance);
144  }
145 
146  template<typename Scalar>
148  {
149  this->free();
150  }
151 
152  template<typename Scalar>
154  {
155  if (this->paralutionSolver)
156  delete this->paralutionSolver;
157  this->paralutionSolver = nullptr;
158  this->sln = nullptr;
159  }
160 
161  template<typename Scalar>
163  {
164  if (this->paralutionSolver)
165  delete this->paralutionSolver;
166  this->paralutionSolver = nullptr;
167  }
168 
169  template<typename Scalar>
171  {
172  this->solve(nullptr);
173  }
174 
175  template<typename Scalar>
177  {
178  // Reinit iff matrix has changed.
179  if (this->reuse_scheme != HERMES_REUSE_MATRIX_STRUCTURE_COMPLETELY)
180  this->reset_internal_solver();
181  this->init_internal_solver();
182 
183  // Set verbose_level.
184  if (this->get_verbose_output())
185  this->paralutionSolver->Verbose(10);
186  else
187  this->paralutionSolver->Verbose(0);
188 
189  // Set tolerances.
190  switch (this->toleranceType)
191  {
192  case AbsoluteTolerance:
193  paralutionSolver->InitTol(this->tolerance, 0., std::numeric_limits<Scalar>::max());
194  break;
195  case RelativeTolerance:
196  paralutionSolver->InitTol(0., this->tolerance, std::numeric_limits<Scalar>::max());
197  break;
198  case DivergenceTolerance:
199  paralutionSolver->InitTol(0., 0., this->tolerance);
200  break;
201  }
202 
203  // Set max iters.
204  paralutionSolver->InitMaxIter(this->max_iters);
205  }
206 
207  template<typename Scalar>
209  {
210  // Handle sln.
211  if (this->sln && this->sln != initial_guess)
212  free_with_check(this->sln);
213  this->sln = malloc_with_check<AbstractParalutionLinearMatrixSolver<Scalar>, Scalar>(this->get_matrix_size(), this);
214 
215  // Create initial guess.
216  if (initial_guess)
217  memcpy(this->sln, initial_guess, this->get_matrix_size() * sizeof(Scalar));
218  else
219  memset(this->sln, 0, this->get_matrix_size() * sizeof(Scalar));
220 
221  paralution::LocalVector<Scalar> x;
222  x.SetDataPtr(&this->sln, "Initial guess", matrix->get_size());
223 
224  // Handle the situation when rhs == 0(vector).
225  if (std::abs(rhs->get_paralutionVector()->Norm()) < Hermes::HermesEpsilon)
226  {
227  x.LeaveDataPtr(&this->sln);
228  return;
229  }
230 
231  // (Re-)init.
232  this->presolve_init();
233 
234  // Move to Accelerators.
235  if (HermesCommonApi.get_integral_param_value(useAccelerators))
236  {
237  this->paralutionSolver->MoveToAccelerator();
238  this->matrix->get_paralutionMatrix().MoveToAccelerator();
239  this->rhs->get_paralutionVector()->MoveToAccelerator();
240  x.MoveToAccelerator();
241  }
242 
243  // Solve.
244  paralutionSolver->Solve(*rhs->get_paralutionVector(), &x);
245 
246  // Store num_iters.
247  num_iters = paralutionSolver->GetIterationCount();
248 
249  // Store final_residual
250  final_residual = paralutionSolver->GetCurrentResidual();
251 
252  // Destroy the paralution vector, keeping the data in sln.
253  x.LeaveDataPtr(&this->sln);
254  }
255 
256  template<typename Scalar>
258  {
259  return matrix->get_size();
260  }
261 
262  template<typename Scalar>
264  {
265  return this->num_iters;
266  }
267 
268  template<typename Scalar>
270  {
271  return final_residual;
272  }
273 
274  template<typename Scalar>
275  IterativeParalutionLinearMatrixSolver<Scalar>::IterativeParalutionLinearMatrixSolver() : AbstractParalutionLinearMatrixSolver<Scalar>(), IterSolver<Scalar>(nullptr, nullptr), LoopSolver<Scalar>(nullptr, nullptr), preconditioner(nullptr)
276  {
278  }
279 
280  template<typename Scalar>
282  {
283  if (preconditioner)
284  {
285  delete preconditioner;
286  preconditioner = nullptr;
287  }
289  }
290 
291  template<typename Scalar>
293  {
295  }
296 
297  template<typename Scalar>
299  {
300  if (preconditioner)
301  {
302  delete preconditioner;
303  preconditioner = nullptr;
304  }
305  }
306 
307  template<typename Scalar>
309  {
310  IterSolver<double>::set_solver_type(iterSolverType);
311  this->reset_internal_solver();
312  }
313 
314  template<typename Scalar>
315  paralution::IterativeLinearSolver<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>*
317  {
318  switch (type)
319  {
320  case CG:
321  {
322  return new paralution::CG<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
323  }
324  break;
325  case GMRES:
326  {
327  return new paralution::GMRES<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
328  }
329  break;
330  case BiCGStab:
331  {
332  return new paralution::BiCGStab<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
333  }
334  break;
335 #if __PARALUTION_VER >= 500
336  case CR:
337  {
338  return new paralution::CR<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
339  }
340  break;
341  case IDR:
342  {
343  return new paralution::IDR<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
344  }
345  break;
346 #endif
347  default:
348  throw Hermes::Exceptions::Exception("A wrong solver type detected in PARALUTION.");
349  return nullptr;
350  }
351  }
352 
353  template<typename Scalar>
355  {
356  // Create a solver according to the current type settings.
357  if (!this->paralutionSolver)
358  {
359  this->paralutionSolver = this->return_paralutionSolver(this->iterSolverType);
360 
361  // Set operator, preconditioner, build.
362  if (this->preconditioner)
363  this->paralutionSolver->SetPreconditioner(this->preconditioner->get_paralutionPreconditioner());
364  this->paralutionSolver->SetOperator(this->matrix->get_paralutionMatrix());
365  this->paralutionSolver->Build();
366  }
367  }
368 
369  template<typename Scalar>
371  {
372  if (this->preconditioner)
373  delete this->preconditioner;
374 
375  Preconditioners::ParalutionPrecond<Scalar>* paralutionPreconditioner = dynamic_cast<Preconditioners::ParalutionPrecond<Scalar>*>(pc);
376  if (paralutionPreconditioner)
377  this->preconditioner = paralutionPreconditioner;
378  else
379  throw Hermes::Exceptions::Exception("A wrong preconditioner type passed to Paralution.");
380  }
381 
382  template<typename Scalar>
384  {
385  }
386 
387  template<typename Scalar>
389  {
390  AMGSolver<double>::set_smoother(solverType_, preconditionerType_);
391  }
392 
393  template<typename Scalar>
395  {
396  }
397 
398  template<typename Scalar>
400  {
401  // Create a solver according to the current type settings.
402  if (!this->paralutionSolver)
403  {
404  paralution::AMG<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>* AMG_solver;
405  this->paralutionSolver = AMG_solver = new paralution::AMG<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
406  AMG_solver->SetManualSmoothers(true);
407  AMG_solver->SetOperator(this->matrix->get_paralutionMatrix());
408  AMG_solver->BuildHierarchy();
409 
410  // Set operator, smoother, build.
411  int levels = AMG_solver->GetNumLevels();
412  paralution::IterativeLinearSolver<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar >** smoothers = malloc_with_check<AMGParalutionLinearMatrixSolver<Scalar>, paralution::IterativeLinearSolver<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar >*>(levels - 1, this);
413  paralution::Preconditioner<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar >** preconditioners = malloc_with_check<AMGParalutionLinearMatrixSolver<Scalar>, paralution::Preconditioner<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar >*>(levels - 1, this);
414 
415  for (int i = 0; i < levels - 1; ++i)
416  {
417  smoothers[i] = IterativeParalutionLinearMatrixSolver<Scalar>::return_paralutionSolver(this->smootherSolverType);
418  preconditioners[i] = ParalutionPrecond<Scalar>::return_paralutionPreconditioner(this->smootherPreconditionerType);
419 
420  smoothers[i]->SetPreconditioner(*preconditioners[i]);
421  if (this->get_verbose_output())
422  smoothers[i]->Verbose(10);
423  else
424  smoothers[i]->Verbose(0);
425  }
426 
427  AMG_solver->SetSmoother(smoothers);
428  AMG_solver->SetSmootherPreIter(3);
429  AMG_solver->SetSmootherPostIter(3);
430 
431  AMG_solver->Build();
432  }
433  }
434 
435  template class HERMES_API IterativeParalutionLinearMatrixSolver < double > ;
436  template class HERMES_API AMGParalutionLinearMatrixSolver < double > ;
437  }
438 
439  namespace Preconditioners
440  {
441  template<typename Scalar>
443  {
444  switch (preconditionerType)
445  {
446  case Jacobi:
447  this->paralutionPreconditioner = new paralution::Jacobi<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
448  break;
449  case ILU:
450  this->paralutionPreconditioner = new paralution::ILU<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
451  break;
452  case MultiColoredILU:
453  this->paralutionPreconditioner = new paralution::MultiColoredILU<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
454  break;
455  case MultiColoredSGS:
456  this->paralutionPreconditioner = new paralution::MultiColoredSGS<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
457  break;
458  case IC:
459  this->paralutionPreconditioner = new paralution::IC<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
460  break;
461  case AIChebyshev:
462  this->paralutionPreconditioner = new paralution::AIChebyshev<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
463  break;
464 #if __PARALUTION_VER >= 500
465  case MultiElimination:
466  {
467  this->mcilu_p = new paralution::MultiColoredILU < paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar > ;
468  mcilu_p->Set(0);
469 
470  paralution::MultiElimination<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>* multiEliminationPreconditioner =
471  new paralution::MultiElimination<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
472  multiEliminationPreconditioner->Set(*mcilu_p, 2, 0.4);
473  this->paralutionPreconditioner = multiEliminationPreconditioner;
474  }
475  break;
476  case SaddlePoint:
477  {
478  paralution::DiagJacobiSaddlePointPrecond<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>* saddlePointPrecond =
479  new paralution::DiagJacobiSaddlePointPrecond<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
480  this->saddlePoint_p_k = new paralution::FSAI < paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar > ;
481  this->saddlePoint_p_s = new paralution::SPAI < paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar > ;
482  saddlePointPrecond->Set(*this->saddlePoint_p_k, *this->saddlePoint_p_s);
483  this->paralutionPreconditioner = saddlePointPrecond;
484  }
485  break;
486 #endif
487  default:
488  throw Hermes::Exceptions::Exception("A wrong paralution preconditioner type passed to ParalutionPrecond constructor.");
489  }
490  }
491 
492  template<typename Scalar>
493  paralution::Preconditioner<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>& ParalutionPrecond<Scalar>::get_paralutionPreconditioner()
494  {
495 #if __PARALUTION_VER >= 500
496 
497  paralution::DiagJacobiSaddlePointPrecond<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>* saddlePointPrecond =
498  dynamic_cast<paralution::DiagJacobiSaddlePointPrecond<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>*>(this->paralutionPreconditioner);
499  if (saddlePointPrecond)
500  saddlePointPrecond->Set(*this->saddlePoint_p_k, *this->saddlePoint_p_s);
501 #endif
502  return (*this->paralutionPreconditioner);
503  }
504 
505  template<typename Scalar>
506  paralution::Preconditioner<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>* ParalutionPrecond<Scalar>::return_paralutionPreconditioner(PreconditionerType type)
507  {
508  switch (type)
509  {
510  case Jacobi:
511  return new paralution::Jacobi<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
512  break;
513  case ILU:
514  return new paralution::ILU<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
515  break;
516  case MultiColoredILU:
517  return new paralution::MultiColoredILU<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
518  break;
519  case MultiColoredSGS:
520  return new paralution::MultiColoredSGS<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
521  break;
522  case IC:
523  return new paralution::IC<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
524  break;
525  case AIChebyshev:
526  return new paralution::AIChebyshev<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
527  break;
528 #if __PARALUTION_VER >= 500
529  case MultiElimination:
530  return new paralution::MultiElimination<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
531  break;
532  case SaddlePoint:
533  return new paralution::DiagJacobiSaddlePointPrecond<paralution::LocalMatrix<Scalar>, paralution::LocalVector<Scalar>, Scalar>();
534  break;
535 #endif
536  default:
537  throw Hermes::Exceptions::Exception("A wrong preconditioner type passed to ParalutionPrecond constructor.");
538  return nullptr;
539  }
540  }
541 
542  template class HERMES_API ParalutionPrecond < double > ;
543  }
544 }
545 #endif
AMGParalutionLinearMatrixSolver(ParalutionMatrix< Scalar > *m, ParalutionVector< Scalar > *rhs)
virtual void zero()
Utility method.
General namespace for the Hermes library.
Exception interface Basically a std::exception, but with a constructor with string and with print_msg...
Definition: exceptions.h:49
virtual void set_smoother(IterSolverType solverType, PreconditionerType preconditionerType)
Set smoother (an iterative linear matrix solver).
virtual void alloc(unsigned int ndofs)
Abstract class to define interface for preconditioners.
Definition: precond.h:57
PARALUTION solver interface.
General CSR Matrix class. (can be used in umfpack, in that case use the CSCMatrix subclass...
Definition: cs_matrix.h:161
Encapsulation of PARALUTION AMG linear solver.
virtual void free()
Utility method.
virtual void alloc(unsigned int ndofs)
Definition: vector.cpp:417
virtual void alloc()
Allocate utility storage (row, column indices, etc.).
File containing common definitions, and basic global enums etc. for HermesCommon. ...
PreconditionerType
The preconditioner type.
Definition: precond.h:42
virtual void zero()
Zero the vector.
Abstract class for defining interface for Algebraic Multigrid solvers. Internal, though utilizable fo...
virtual void zero()
Utility method.
Definition: cs_matrix.cpp:149
ParalutionMatrix(ParalutionMatrixType type=ParalutionMatrixTypeCSR)
Default constructor.
Vector used with MUMPS solver.
Definition: vector.h:116
HERMES_COMMON_API Hermes::Api HermesCommonApi
Global instance used inside Hermes which is also accessible to users.
Definition: api.cpp:158
virtual int get_num_iters()
Get number of iterations.
virtual void set_tolerance(double tol)
virtual void free()
free the memory
Definition: vector.cpp:440
virtual void init_internal_solver()
Set internal solver for the current solution.
virtual void set_max_iters(int iters)
Abstract middle-class for solvers that work in a loop of a kind (iterative, multigrid, ...)
General Paralution matrix.
ParalutionVector()
Default constructor.
Abstract class for defining interface for iterative solvers. Internal, though utilizable for defining...
virtual void init_internal_solver()
Set internal solver for the current solution.
virtual void set_precond(Precond< Scalar > *pc)
Set preconditioner.
virtual double get_residual_norm()
Get the residual value.
virtual void set_smoother(IterSolverType solverType, PreconditionerType preconditionerType)
Set smoother (an iterative linear matrix solver).
ABSTRACT class containing common functionality of both PARALUTION iterative and AMG linear solver...
ParalutionPrecond(PreconditionerType preconditionerType)
void reset_internal_solver()
Internal solver is not reusable and will have to be re-created.
Class representing the vector for UMFPACK.
virtual void free()
free the memory
Encapsulation of PARALUTION iterative linear solver.
Scalar * v
Raw data.
Definition: vector.h:149
virtual void free()
Utility method.
Definition: cs_matrix.cpp:133
virtual void alloc()
Allocate utility storage (row, column indices, etc.).
Definition: cs_matrix.cpp:101
void set_solver_type(IterSolverType iterSolverType)