1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 // vi: set et ts=8 sw=2 sts=2: 3 #ifndef DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH 4 #define DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH 5 6 #include <dune/common/deprecated.hh> 7 #include <dune/common/parallel/mpihelper.hh> 8 9 #include <dune/istl/owneroverlapcopy.hh> 10 #include <dune/istl/solvercategory.hh> 11 #include <dune/istl/operators.hh> 12 #include <dune/istl/solvers.hh> 13 #include <dune/istl/preconditioners.hh> 14 #include <dune/istl/scalarproducts.hh> 15 #include <dune/istl/paamg/amg.hh> 16 #include <dune/istl/paamg/pinfo.hh> 17 #include <dune/istl/io.hh> 18 #include <dune/istl/superlu.hh> 19 #include <dune/istl/umfpack.hh> 20 21 #include <dune/pdelab/constraints/common/constraints.hh> 22 #include <dune/pdelab/gridfunctionspace/genericdatahandle.hh> 23 #include <dune/pdelab/backend/solver.hh> 24 #include <dune/pdelab/backend/istl/vector.hh> 25 #include <dune/pdelab/backend/istl/bcrsmatrix.hh> 26 27 namespace Dune { 28 namespace PDELab { 29 30 //! \addtogroup Backend 31 //! \ingroup PDELab 32 //! \{ 33 34 35 /**Create ISTL operator from a grid operator object 36 * 37 * In the nonlinear case the operator need to be linearized by setting a 38 * linearization point before it can be used. 39 * 40 * \tparam X Trial vector. 41 * \tparam Y Test vector. 42 * \tparam GO Grid operator that implements the jacobian apply 43 */ 44 template<typename X, typename Y, typename GO> 45 class OnTheFlyOperator : public Dune::LinearOperator<X,Y> 46 { 47 public: 48 typedef X domain_type; 49 typedef Y range_type; 50 typedef typename X::field_type field_type; 51 static constexpr bool isLinear = GO::LocalAssembler::isLinear(); 52 53 OnTheFlyOperator(const GO & go_)54 OnTheFlyOperator (const GO& go_) 55 : go(go_) 56 , u_(nullptr) 57 {} 58 59 //! Set linearization point. 60 //! Must be called before apply() and applyscaleadd() for nonlinear problems. setLinearizationPoint(const X & u)61 void setLinearizationPoint(const X& u) 62 { 63 u_ = &u; 64 } 65 apply(const X & x,Y & y) const66 virtual void apply (const X& x, Y& y) const override 67 { 68 y = 0.0; 69 if (isLinear) 70 go.jacobian_apply(x,y); 71 else { 72 if (u_ == nullptr) 73 DUNE_THROW(Dune::InvalidStateException, "You seem to apply a nonlinear operator without setting the linearization point first!"); 74 go.jacobian_apply(*u_, x, y); 75 } 76 } 77 applyscaleadd(field_type alpha,const X & x,Y & y) const78 virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const override 79 { 80 Y temp(y); 81 temp = 0.0; 82 if (isLinear) 83 go.jacobian_apply(x,temp); 84 else { 85 if (u_ == nullptr) 86 DUNE_THROW(Dune::InvalidStateException, "You seem to apply a nonlinear operator without setting the linearization point first!"); 87 go.jacobian_apply(*u_, x, temp); 88 } 89 y.axpy(alpha,temp); 90 } 91 category() const92 SolverCategory::Category category() const override 93 { 94 return SolverCategory::sequential; 95 } 96 97 private: 98 const GO& go; 99 const X* u_; 100 }; 101 102 //============================================================================== 103 // Here we add some standard linear solvers conforming to the linear solver 104 // interface required to solve linear and nonlinear problems. 105 //============================================================================== 106 107 //===================================================================== 108 // First we add some base classes where the preconditioner is specified 109 //===================================================================== 110 111 template<template<class> class Solver> 112 class ISTLBackend_SEQ_Richardson 113 : public SequentialNorm, public LinearResultStorage 114 { 115 public: 116 /*! \brief make a linear solver object 117 118 \param[in] maxiter_ maximum number of iterations to do 119 \param[in] verbose_ print messages if true 120 */ ISTLBackend_SEQ_Richardson(unsigned maxiter_=5000,int verbose_=1)121 explicit ISTLBackend_SEQ_Richardson(unsigned maxiter_=5000, int verbose_=1) 122 : maxiter(maxiter_), verbose(verbose_) 123 {} 124 125 /*! \brief solve the given linear system 126 127 \param[in] A the given matrix 128 \param[out] z the solution vector to be computed 129 \param[in] r right hand side 130 \param[in] reduction to be achieved 131 */ 132 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)133 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 134 { 135 using Backend::Native; 136 using Backend::native; 137 138 Dune::MatrixAdapter<Native<M>, 139 Native<V>, 140 Native<W>> opa(native(A)); 141 Dune::Richardson<Native<V>,Native<W> > prec(0.7); 142 Solver<Native<V> > solver(opa, prec, reduction, maxiter, verbose); 143 Dune::InverseOperatorResult stat; 144 solver.apply(native(z), native(r), stat); 145 res.converged = stat.converged; 146 res.iterations = stat.iterations; 147 res.elapsed = stat.elapsed; 148 res.reduction = stat.reduction; 149 res.conv_rate = stat.conv_rate; 150 } 151 152 private: 153 unsigned maxiter; 154 int verbose; 155 }; 156 157 template<class GO, template<class> class Solver> 158 class ISTLBackend_SEQ_MatrixFree_Richardson 159 : public SequentialNorm, public LinearResultStorage 160 { 161 using V = typename GO::Traits::Domain; 162 using W = typename GO::Traits::Range; 163 public: 164 /*! \brief make a linear solver object 165 166 \param[in] maxiter_ maximum number of iterations to do 167 \param[in] verbose_ print messages if true 168 */ ISTLBackend_SEQ_MatrixFree_Richardson(const GO & go,unsigned maxiter=5000,int verbose=1)169 explicit ISTLBackend_SEQ_MatrixFree_Richardson(const GO& go, unsigned maxiter=5000, int verbose=1) 170 : opa_(go) 171 , maxiter_(maxiter) 172 , verbose_(verbose) 173 {} 174 175 /*! \brief solve the given linear system 176 177 \param[in] A the given matrix 178 \param[out] z the solution vector to be computed 179 \param[in] r right hand side 180 \param[in] reduction to be achieved 181 */ apply(V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)182 void apply(V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 183 { 184 Dune::Richardson<V,W> prec(1.0); 185 Solver<V> solver(opa_, prec, reduction, maxiter_, verbose_); 186 Dune::InverseOperatorResult stat; 187 solver.apply(z, r, stat); 188 res.converged = stat.converged; 189 res.iterations = stat.iterations; 190 res.elapsed = stat.elapsed; 191 res.reduction = stat.reduction; 192 res.conv_rate = stat.conv_rate; 193 } 194 195 //! Set position of jacobian, ust be called before apply() for nonlinear problems. setLinearizationPoint(const V & u)196 void setLinearizationPoint(const V& u) 197 { 198 opa_.setLinearizationPoint(u); 199 } 200 201 private: 202 Dune::PDELab::OnTheFlyOperator<V,W,GO> opa_; 203 unsigned maxiter_; 204 int verbose_; 205 }; 206 207 template<template<class,class,class,int> class Preconditioner, 208 template<class> class Solver> 209 class ISTLBackend_SEQ_Base 210 : public SequentialNorm, public LinearResultStorage 211 { 212 public: 213 /*! \brief make a linear solver object 214 215 \param[in] maxiter_ maximum number of iterations to do 216 \param[in] verbose_ print messages if true 217 */ ISTLBackend_SEQ_Base(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)218 explicit ISTLBackend_SEQ_Base(unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 219 : maxiter(maxiter_), verbose(verbose_), preconditioner_steps(preconditioner_steps_) 220 {} 221 222 223 224 /*! \brief solve the given linear system 225 226 \param[in] A the given matrix 227 \param[out] z the solution vector to be computed 228 \param[in] r right hand side 229 \param[in] reduction to be achieved 230 */ 231 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)232 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 233 { 234 using Backend::Native; 235 using Backend::native; 236 237 Dune::MatrixAdapter<Native<M>, 238 Native<V>, 239 Native<W>> opa(native(A)); 240 Preconditioner<Native<M>, 241 Native<V>, 242 Native<W>, 243 1> prec(native(A), preconditioner_steps, 1.0); 244 Solver<Native<V>> solver(opa, prec, reduction, maxiter, verbose); 245 Dune::InverseOperatorResult stat; 246 solver.apply(native(z), native(r), stat); 247 res.converged = stat.converged; 248 res.iterations = stat.iterations; 249 res.elapsed = stat.elapsed; 250 res.reduction = stat.reduction; 251 res.conv_rate = stat.conv_rate; 252 } 253 254 private: 255 unsigned maxiter; 256 int verbose; 257 unsigned preconditioner_steps; 258 }; 259 260 template<template<typename> class Solver> 261 class ISTLBackend_SEQ_ILU0 262 : public SequentialNorm, public LinearResultStorage 263 { 264 public: 265 /*! \brief make a linear solver object 266 267 \param[in] maxiter_ maximum number of iterations to do 268 \param[in] verbose_ print messages if true 269 */ ISTLBackend_SEQ_ILU0(unsigned maxiter_=5000,int verbose_=1)270 explicit ISTLBackend_SEQ_ILU0 (unsigned maxiter_=5000, int verbose_=1) 271 : maxiter(maxiter_), verbose(verbose_) 272 {} 273 /*! \brief solve the given linear system 274 275 \param[in] A the given matrix 276 \param[out] z the solution vector to be computed 277 \param[in] r right hand side 278 \param[in] reduction to be achieved 279 */ 280 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)281 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 282 { 283 using Backend::Native; 284 using Backend::native; 285 Dune::MatrixAdapter<Native<M>, 286 Native<V>, 287 Native<W>> opa(native(A)); 288 Dune::SeqILU<Native<M>, 289 Native<V>, 290 Native<W> 291 > ilu0(native(A), 1.0); 292 Solver<Native<V>> solver(opa, ilu0, reduction, maxiter, verbose); 293 Dune::InverseOperatorResult stat; 294 solver.apply(native(z), native(r), stat); 295 res.converged = stat.converged; 296 res.iterations = stat.iterations; 297 res.elapsed = stat.elapsed; 298 res.reduction = stat.reduction; 299 res.conv_rate = stat.conv_rate; 300 } 301 private: 302 unsigned maxiter; 303 int verbose; 304 }; 305 306 template<template<typename> class Solver> 307 class ISTLBackend_SEQ_ILUn 308 : public SequentialNorm, public LinearResultStorage 309 { 310 public: 311 /*! \brief make a linear solver object 312 \param[in] n The number of levels to be used. 313 \param[in] w The relaxation factor. 314 \param[in] maxiter_ maximum number of iterations to do 315 \param[in] verbose_ print messages if true 316 */ ISTLBackend_SEQ_ILUn(int n,double w,unsigned maxiter_=5000,int verbose_=1)317 ISTLBackend_SEQ_ILUn (int n, double w, unsigned maxiter_=5000, int verbose_=1) 318 : n_(n), w_(w), maxiter(maxiter_), verbose(verbose_) 319 {} 320 /*! \brief solve the given linear system 321 322 \param[in] A the given matrix 323 \param[out] z the solution vector to be computed 324 \param[in] r right hand side 325 \param[in] reduction to be achieved 326 */ 327 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)328 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 329 { 330 using Backend::Native; 331 using Backend::native; 332 Dune::MatrixAdapter<Native<M>, 333 Native<V>, 334 Native<W> 335 > opa(native(A)); 336 Dune::SeqILU<Native<M>, 337 Native<V>, 338 Native<W> 339 > ilun(native(A), n_, w_, false); 340 Solver<Native<V>> solver(opa, ilun, reduction, maxiter, verbose); 341 Dune::InverseOperatorResult stat; 342 solver.apply(native(z), native(r), stat); 343 res.converged = stat.converged; 344 res.iterations = stat.iterations; 345 res.elapsed = stat.elapsed; 346 res.reduction = stat.reduction; 347 res.conv_rate = stat.conv_rate; 348 } 349 private: 350 int n_; 351 double w_; 352 353 unsigned maxiter; 354 int verbose; 355 }; 356 357 //======================================== 358 // Start with matrix based solver backends 359 //======================================== 360 361 //! \addtogroup PDELab_seqsolvers Sequential Solvers 362 //! \{ 363 364 /** 365 * @brief Backend for sequential loop solver with Jacobi preconditioner. 366 */ 367 class ISTLBackend_SEQ_LOOP_Jac 368 : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::LoopSolver> 369 { 370 public: 371 /*! \brief make a linear solver object 372 \param[in] maxiter_ maximum number of iterations to do 373 \param[in] verbose_ print messages if true 374 */ ISTLBackend_SEQ_LOOP_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)375 explicit ISTLBackend_SEQ_LOOP_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 376 : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::LoopSolver>(maxiter_, verbose_, preconditioner_steps_) 377 {} 378 }; 379 380 /** 381 * @brief Backend for sequential BiCGSTAB solver with Richardson 382 * precondition (equivalent to no preconditioner for Richards with 383 * parameter=1.0). 384 */ 385 class ISTLBackend_SEQ_BCGS_Richardson 386 : public ISTLBackend_SEQ_Richardson<Dune::BiCGSTABSolver> 387 { 388 public: 389 /*! \brief make a linear solver object 390 \param[in] maxiter_ maximum number of iterations to do 391 \param[in] verbose_ print messages if true 392 */ ISTLBackend_SEQ_BCGS_Richardson(unsigned maxiter_=5000,int verbose_=1)393 explicit ISTLBackend_SEQ_BCGS_Richardson (unsigned maxiter_=5000, int verbose_=1) 394 : ISTLBackend_SEQ_Richardson<Dune::BiCGSTABSolver>(maxiter_, verbose_) 395 {} 396 }; 397 398 /** 399 * @brief Backend for sequential BiCGSTAB solver with Jacobi preconditioner. 400 */ 401 class ISTLBackend_SEQ_BCGS_Jac 402 : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::BiCGSTABSolver> 403 { 404 public: 405 /*! \brief make a linear solver object 406 \param[in] maxiter_ maximum number of iterations to do 407 \param[in] verbose_ print messages if true 408 */ ISTLBackend_SEQ_BCGS_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)409 explicit ISTLBackend_SEQ_BCGS_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 410 : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::BiCGSTABSolver>(maxiter_, verbose_, preconditioner_steps_) 411 {} 412 }; 413 414 /** 415 * @brief Backend for sequential BiCGSTAB solver with SSOR preconditioner. 416 */ 417 class ISTLBackend_SEQ_BCGS_SSOR 418 : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::BiCGSTABSolver> 419 { 420 public: 421 /*! \brief make a linear solver object 422 423 \param[in] maxiter_ maximum number of iterations to do 424 \param[in] verbose_ print messages if true 425 */ ISTLBackend_SEQ_BCGS_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)426 explicit ISTLBackend_SEQ_BCGS_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 427 : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::BiCGSTABSolver>(maxiter_, verbose_, preconditioner_steps_) 428 {} 429 }; 430 431 /** 432 * @brief Backend for sequential BiCGSTAB solver with ILU0 preconditioner. 433 */ 434 class ISTLBackend_SEQ_BCGS_ILU0 435 : public ISTLBackend_SEQ_ILU0<Dune::BiCGSTABSolver> 436 { 437 public: 438 /*! \brief make a linear solver object 439 440 \param[in] maxiter_ maximum number of iterations to do 441 \param[in] verbose_ print messages if true 442 */ ISTLBackend_SEQ_BCGS_ILU0(unsigned maxiter_=5000,int verbose_=1)443 explicit ISTLBackend_SEQ_BCGS_ILU0 (unsigned maxiter_=5000, int verbose_=1) 444 : ISTLBackend_SEQ_ILU0<Dune::BiCGSTABSolver>(maxiter_, verbose_) 445 {} 446 }; 447 448 /** 449 * @brief Backend for sequential conjugate gradient solver with ILU0 preconditioner. 450 */ 451 class ISTLBackend_SEQ_CG_ILU0 452 : public ISTLBackend_SEQ_ILU0<Dune::CGSolver> 453 { 454 public: 455 /*! \brief make a linear solver object 456 457 \param[in] maxiter_ maximum number of iterations to do 458 \param[in] verbose_ print messages if true 459 */ ISTLBackend_SEQ_CG_ILU0(unsigned maxiter_=5000,int verbose_=1)460 explicit ISTLBackend_SEQ_CG_ILU0 (unsigned maxiter_=5000, int verbose_=1) 461 : ISTLBackend_SEQ_ILU0<Dune::CGSolver>(maxiter_, verbose_) 462 {} 463 }; 464 465 //! \brief Sequential BiCGStab solver with ILU0 preconditioner 466 class ISTLBackend_SEQ_BCGS_ILUn 467 : public ISTLBackend_SEQ_ILUn<Dune::BiCGSTABSolver> 468 { 469 public: 470 /*! \brief make a linear solver object 471 472 473 \param[in] n_ The number of levels to be used. 474 \param[in] w_ The relaxation factor. 475 \param[in] maxiter_ maximum number of iterations to do 476 \param[in] verbose_ print messages if true 477 */ ISTLBackend_SEQ_BCGS_ILUn(int n_,double w_=1.0,unsigned maxiter_=5000,int verbose_=1)478 explicit ISTLBackend_SEQ_BCGS_ILUn (int n_, double w_=1.0, unsigned maxiter_=5000, int verbose_=1) 479 : ISTLBackend_SEQ_ILUn<Dune::BiCGSTABSolver>(n_, w_, maxiter_, verbose_) 480 {} 481 }; 482 483 //! \brief Sequential congute gradient solver with ILU0 preconditioner 484 class ISTLBackend_SEQ_CG_ILUn 485 : public ISTLBackend_SEQ_ILUn<Dune::CGSolver> 486 { 487 public: 488 /*! \brief make a linear solver object 489 490 491 \param[in] n_ The number of levels to be used. 492 \param[in] w_ The relaxation factor. 493 \param[in] maxiter_ maximum number of iterations to do 494 \param[in] verbose_ print messages if true 495 */ ISTLBackend_SEQ_CG_ILUn(int n_,double w_=1.0,unsigned maxiter_=5000,int verbose_=1)496 explicit ISTLBackend_SEQ_CG_ILUn (int n_, double w_=1.0, unsigned maxiter_=5000, int verbose_=1) 497 : ISTLBackend_SEQ_ILUn<Dune::CGSolver>(n_, w_, maxiter_, verbose_) 498 {} 499 }; 500 501 /** 502 * @brief Backend for sequential conjugate gradient solver with SSOR preconditioner. 503 */ 504 class ISTLBackend_SEQ_CG_SSOR 505 : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::CGSolver> 506 { 507 public: 508 /*! \brief make a linear solver object 509 510 \param[in] maxiter_ maximum number of iterations to do 511 \param[in] verbose_ print messages if true 512 */ ISTLBackend_SEQ_CG_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)513 explicit ISTLBackend_SEQ_CG_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 514 : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::CGSolver>(maxiter_, verbose_, preconditioner_steps_) 515 {} 516 }; 517 518 /** 519 * @brief Backend using a MINRes solver preconditioned by SSOR. 520 */ 521 class ISTLBackend_SEQ_MINRES_SSOR 522 : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::MINRESSolver> 523 { 524 public: 525 /*! \brief make a linear solver object 526 527 \param[in] maxiter_ maximum number of iterations to do 528 \param[in] verbose_ print messages if true 529 */ ISTLBackend_SEQ_MINRES_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)530 explicit ISTLBackend_SEQ_MINRES_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 531 : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::MINRESSolver>(maxiter_, verbose_, preconditioner_steps_) 532 {} 533 }; 534 535 /** 536 * @brief Backend for conjugate gradient solver with Jacobi preconditioner. 537 */ 538 class ISTLBackend_SEQ_CG_Jac 539 : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::CGSolver> 540 { 541 public: 542 /*! \brief make a linear solver object 543 \param[in] maxiter_ maximum number of iterations to do 544 \param[in] verbose_ print messages if true 545 */ ISTLBackend_SEQ_CG_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)546 explicit ISTLBackend_SEQ_CG_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1) 547 : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::CGSolver>(maxiter_, verbose_, preconditioner_steps_) 548 {} 549 }; 550 551 #if HAVE_SUPERLU || DOXYGEN 552 /** 553 * @brief Solver backend using SuperLU as a direct solver. 554 */ 555 class ISTLBackend_SEQ_SuperLU 556 : public SequentialNorm, public LinearResultStorage 557 { 558 public: 559 /*! \brief make a linear solver object 560 561 \param[in] verbose_ print messages if true 562 */ ISTLBackend_SEQ_SuperLU(int verbose_=1)563 explicit ISTLBackend_SEQ_SuperLU (int verbose_=1) 564 : verbose(verbose_) 565 {} 566 567 568 /*! \brief make a linear solver object 569 570 \param[in] maxiter Maximum number of allowed steps (ignored) 571 \param[in] verbose_ print messages if true 572 */ ISTLBackend_SEQ_SuperLU(int maxiter,int verbose_)573 ISTLBackend_SEQ_SuperLU (int maxiter, int verbose_) 574 : verbose(verbose_) 575 {} 576 577 /*! \brief solve the given linear system 578 579 \param[in] A the given matrix 580 \param[out] z the solution vector to be computed 581 \param[in] r right hand side 582 \param[in] reduction to be achieved 583 */ 584 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)585 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 586 { 587 using Backend::Native; 588 using Backend::native; 589 using ISTLM = Native<M>; 590 Dune::SuperLU<ISTLM> solver(native(A), verbose); 591 Dune::InverseOperatorResult stat; 592 solver.apply(native(z), native(r), stat); 593 res.converged = stat.converged; 594 res.iterations = stat.iterations; 595 res.elapsed = stat.elapsed; 596 res.reduction = stat.reduction; 597 res.conv_rate = stat.conv_rate; 598 } 599 600 private: 601 int verbose; 602 }; 603 #endif // HAVE_SUPERLU || DOXYGEN 604 605 #if HAVE_SUITESPARSE_UMFPACK || DOXYGEN 606 /** 607 * @brief Solver backend using UMFPack as a direct solver. 608 */ 609 class ISTLBackend_SEQ_UMFPack 610 : public SequentialNorm, public LinearResultStorage 611 { 612 public: 613 /*! \brief make a linear solver object 614 615 \param[in] verbose_ print messages if true 616 */ ISTLBackend_SEQ_UMFPack(int verbose_=1)617 explicit ISTLBackend_SEQ_UMFPack (int verbose_=1) 618 : verbose(verbose_) 619 {} 620 621 622 /*! \brief make a linear solver object 623 624 \param[in] maxiter Maximum number of allowed steps (ignored) 625 \param[in] verbose_ print messages if true 626 */ ISTLBackend_SEQ_UMFPack(int maxiter,int verbose_)627 ISTLBackend_SEQ_UMFPack (int maxiter, int verbose_) 628 : verbose(verbose_) 629 {} 630 631 /*! \brief solve the given linear system 632 633 \param[in] A the given matrix 634 \param[out] z the solution vector to be computed 635 \param[in] r right hand side 636 \param[in] reduction to be achieved 637 */ 638 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)639 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 640 { 641 using Backend::native; 642 using ISTLM = Backend::Native<M>; 643 Dune::UMFPack<ISTLM> solver(native(A), verbose); 644 Dune::InverseOperatorResult stat; 645 solver.apply(native(z), native(r), stat); 646 res.converged = stat.converged; 647 res.iterations = stat.iterations; 648 res.elapsed = stat.elapsed; 649 res.reduction = stat.reduction; 650 res.conv_rate = stat.conv_rate; 651 } 652 653 private: 654 int verbose; 655 }; 656 #endif // HAVE_SUITESPARSE_UMFPACK || DOXYGEN 657 658 //! Solver to be used for explicit time-steppers with (block-)diagonal mass matrix 659 class ISTLBackend_SEQ_ExplicitDiagonal 660 : public SequentialNorm, public LinearResultStorage 661 { 662 public: 663 /*! \brief make a linear solver object 664 */ ISTLBackend_SEQ_ExplicitDiagonal()665 ISTLBackend_SEQ_ExplicitDiagonal () 666 {} 667 668 /*! \brief solve the given linear system 669 670 \param[in] A the given matrix 671 \param[out] z the solution vector to be computed 672 \param[in] r right hand side 673 \param[in] reduction to be achieved 674 */ 675 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)676 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction) 677 { 678 using Backend::Native; 679 Dune::SeqJac<Native<M>, 680 Native<V>, 681 Native<W> 682 > jac(Backend::native(A),1,1.0); 683 jac.pre(z,r); 684 jac.apply(z,r); 685 jac.post(z); 686 res.converged = true; 687 res.iterations = 1; 688 res.elapsed = 0.0; 689 res.reduction = reduction; 690 res.conv_rate = reduction; // pow(reduction,1.0/1) 691 } 692 }; 693 694 //! \} Sequential Solvers 695 696 /** 697 * @brief Class providing some statistics of the AMG solver. 698 * 699 */ 700 struct ISTLAMGStatistics 701 { 702 /** 703 * @brief The needed for computing the parallel information and 704 * for adapting the linear system. 705 */ 706 double tprepare; 707 /** @brief the number of levels in the AMG hierarchy. */ 708 int levels; 709 /** @brief The time spent in solving the system (without building the hierarchy. */ 710 double tsolve; 711 /** @brief The time needed for building the AMG hierarchy (coarsening). */ 712 double tsetup; 713 /** @brief The number of iterations performed until convergence was reached. */ 714 int iterations; 715 /** @brief True if a direct solver was used on the coarset level. */ 716 bool directCoarseLevelSolver; 717 }; 718 719 template<class GO, template<class,class,class,int> class Preconditioner, template<class> class Solver, 720 bool skipBlocksizeCheck = false> 721 class ISTLBackend_SEQ_AMG : public LinearResultStorage 722 { 723 typedef typename GO::Traits::TrialGridFunctionSpace GFS; 724 typedef typename GO::Traits::Jacobian M; 725 typedef Backend::Native<M> MatrixType; 726 typedef typename GO::Traits::Domain V; 727 typedef Backend::Native<V> VectorType; 728 typedef Preconditioner<MatrixType,VectorType,VectorType,1> Smoother; 729 typedef Dune::MatrixAdapter<MatrixType,VectorType,VectorType> Operator; 730 typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs; 731 typedef Dune::Amg::AMG<Operator,VectorType,Smoother> AMG; 732 typedef Dune::Amg::Parameters Parameters; 733 734 public: ISTLBackend_SEQ_AMG(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)735 ISTLBackend_SEQ_AMG(unsigned maxiter_=5000, int verbose_=1, 736 bool reuse_=false, bool usesuperlu_=true) 737 : maxiter(maxiter_), params(15,2000), verbose(verbose_), 738 reuse(reuse_), firstapply(true), usesuperlu(usesuperlu_) 739 { 740 params.setDefaultValuesIsotropic(GFS::Traits::GridViewType::Traits::Grid::dimension); 741 params.setDebugLevel(verbose_); 742 #if !HAVE_SUPERLU 743 if (usesuperlu == true) 744 { 745 std::cout << "WARNING: You are using AMG without SuperLU!" 746 << " Please consider installing SuperLU," 747 << " or set the usesuperlu flag to false" 748 << " to suppress this warning." << std::endl; 749 } 750 #endif 751 } 752 753 /*! \brief set AMG parameters 754 755 \param[in] params_ a parameter object of Type Dune::Amg::Parameters 756 */ setparams(Parameters params_)757 void setparams(Parameters params_) 758 { 759 params = params_; 760 } 761 762 //! Set whether the AMG should be reused again during call to apply(). setReuse(bool reuse_)763 void setReuse(bool reuse_) 764 { 765 reuse = reuse_; 766 } 767 768 //! Return whether the AMG is reused during call to apply() getReuse() const769 bool getReuse() const 770 { 771 return reuse; 772 } 773 774 /*! \brief compute global norm of a vector 775 776 \param[in] v the given vector 777 */ norm(const V & v) const778 typename V::ElementType norm (const V& v) const 779 { 780 return Backend::native(v).two_norm(); 781 } 782 783 /*! \brief solve the given linear system 784 785 \param[in] A the given matrix 786 \param[out] z the solution vector to be computed 787 \param[in] r right hand side 788 \param[in] reduction to be achieved 789 */ apply(M & A,V & z,V & r,typename Dune::template FieldTraits<typename V::ElementType>::real_type reduction)790 void apply(M& A, V& z, V& r, typename Dune::template FieldTraits<typename V::ElementType >::real_type reduction) 791 { 792 Timer watch; 793 MatrixType& mat = Backend::native(A); 794 typedef Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<MatrixType, 795 Dune::Amg::FirstDiagonal> > Criterion; 796 SmootherArgs smootherArgs; 797 smootherArgs.iterations = 1; 798 smootherArgs.relaxationFactor = 1; 799 800 Criterion criterion(params); 801 //only construct a new AMG if the matrix changes 802 if (reuse==false || firstapply==true){ 803 oop.reset(new Operator(mat)); 804 amg.reset(new AMG(*oop, criterion, smootherArgs)); 805 firstapply = false; 806 stats.tsetup = watch.elapsed(); 807 stats.levels = amg->maxlevels(); 808 stats.directCoarseLevelSolver=amg->usesDirectCoarseLevelSolver(); 809 } 810 watch.reset(); 811 Dune::InverseOperatorResult stat; 812 813 Solver<VectorType> solver(*oop,*amg,reduction,maxiter,verbose); 814 solver.apply(Backend::native(z),Backend::native(r),stat); 815 stats.tsolve= watch.elapsed(); 816 res.converged = stat.converged; 817 res.iterations = stat.iterations; 818 res.elapsed = stat.elapsed; 819 res.reduction = stat.reduction; 820 res.conv_rate = stat.conv_rate; 821 } 822 823 824 /** 825 * @brief Get statistics of the AMG solver (no of levels, timings). 826 * @return statistis of the AMG solver. 827 */ statistics() const828 const ISTLAMGStatistics& statistics() const 829 { 830 return stats; 831 } 832 833 private: 834 unsigned maxiter; 835 Parameters params; 836 int verbose; 837 bool reuse; 838 bool firstapply; 839 bool usesuperlu; 840 std::shared_ptr<Operator> oop; 841 std::shared_ptr<AMG> amg; 842 ISTLAMGStatistics stats; 843 }; 844 845 //! \addtogroup PDELab_seqsolvers Sequential Solvers 846 //! \{ 847 848 /** 849 * @brief Sequential conjugate gradient solver preconditioned with AMG smoothed by SSOR 850 * @tparam GO The type of the grid operator 851 * (or the fakeGOTraits class for the old grid operator space). 852 */ 853 template<class GO> 854 class ISTLBackend_SEQ_CG_AMG_SSOR 855 : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::CGSolver> 856 { 857 858 public: 859 /** 860 * @brief Constructor 861 * @param maxiter_ The maximum number of iterations allowed. 862 * @param verbose_ The verbosity level to use. 863 * @param reuse_ Set true, if the Matrix to be used is always identical 864 * (AMG aggregation is then only performed once). 865 * @param usesuperlu_ Set false, to suppress the no SuperLU warning 866 */ ISTLBackend_SEQ_CG_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)867 ISTLBackend_SEQ_CG_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1, 868 bool reuse_=false, bool usesuperlu_=true) 869 : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::CGSolver> 870 (maxiter_, verbose_, reuse_, usesuperlu_) 871 {} 872 }; 873 874 /** 875 * @brief Sequential BiCGStab solver preconditioned with AMG smoothed by SSOR 876 * @tparam GO The type of the grid operator 877 * (or the fakeGOTraits class for the old grid operator space). 878 */ 879 template<class GO> 880 class ISTLBackend_SEQ_BCGS_AMG_SSOR 881 : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::BiCGSTABSolver> 882 { 883 884 public: 885 /** 886 * @brief Constructor 887 * @param maxiter_ The maximum number of iterations allowed. 888 * @param verbose_ The verbosity level to use. 889 * @param reuse_ Set true, if the Matrix to be used is always identical 890 * (AMG aggregation is then only performed once). 891 * @param usesuperlu_ Set false, to suppress the no SuperLU warning 892 */ ISTLBackend_SEQ_BCGS_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)893 ISTLBackend_SEQ_BCGS_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1, 894 bool reuse_=false, bool usesuperlu_=true) 895 : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::BiCGSTABSolver> 896 (maxiter_, verbose_, reuse_, usesuperlu_) 897 {} 898 }; 899 900 /** 901 * @brief Sequential BiCGSTAB solver preconditioned with AMG smoothed by SOR 902 * @tparam GO The type of the grid operator 903 * (or the fakeGOTraits class for the old grid operator space). 904 */ 905 template<class GO> 906 class ISTLBackend_SEQ_BCGS_AMG_SOR 907 : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::BiCGSTABSolver> 908 { 909 910 public: 911 /** 912 * @brief Constructor 913 * @param maxiter_ The maximum number of iterations allowed. 914 * @param verbose_ The verbosity level to use. 915 * @param reuse_ Set true, if the Matrix to be used is always identical 916 * (AMG aggregation is then only performed once). 917 * @param usesuperlu_ Set false, to suppress the no SuperLU warning 918 */ ISTLBackend_SEQ_BCGS_AMG_SOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)919 ISTLBackend_SEQ_BCGS_AMG_SOR(unsigned maxiter_=5000, int verbose_=1, 920 bool reuse_=false, bool usesuperlu_=true) 921 : ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::BiCGSTABSolver> 922 (maxiter_, verbose_, reuse_, usesuperlu_) 923 {} 924 }; 925 926 /** 927 * @brief Sequential Loop solver preconditioned with AMG smoothed by SSOR 928 * @tparam GO The type of the grid operator 929 * (or the fakeGOTraits class for the old grid operator space). 930 */ 931 template<class GO> 932 class ISTLBackend_SEQ_LS_AMG_SSOR 933 : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::LoopSolver> 934 { 935 936 public: 937 /** 938 * @brief Constructor 939 * @param maxiter_ The maximum number of iterations allowed. 940 * @param verbose_ The verbosity level to use. 941 * @param reuse_ Set true, if the Matrix to be used is always identical 942 * (AMG aggregation is then only performed once). 943 * @param usesuperlu_ Set false, to suppress the no SuperLU warning 944 */ ISTLBackend_SEQ_LS_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)945 ISTLBackend_SEQ_LS_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1, 946 bool reuse_=false, bool usesuperlu_=true) 947 : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::LoopSolver> 948 (maxiter_, verbose_, reuse_, usesuperlu_) 949 {} 950 }; 951 952 /** 953 * @brief Sequential Loop solver preconditioned with AMG smoothed by SOR 954 * @tparam GO The type of the grid operator 955 * (or the fakeGOTraits class for the old grid operator space). 956 */ 957 template<class GO> 958 class ISTLBackend_SEQ_LS_AMG_SOR 959 : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::LoopSolver> 960 { 961 962 public: 963 /** 964 * @brief Constructor 965 * @param maxiter_ The maximum number of iterations allowed. 966 * @param verbose_ The verbosity level to use. 967 * @param reuse_ Set true, if the Matrix to be used is always identical 968 * (AMG aggregation is then only performed once). 969 * @param usesuperlu_ Set false, to suppress the no SuperLU warning 970 */ ISTLBackend_SEQ_LS_AMG_SOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)971 ISTLBackend_SEQ_LS_AMG_SOR(unsigned maxiter_=5000, int verbose_=1, 972 bool reuse_=false, bool usesuperlu_=true) 973 : ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::LoopSolver> 974 (maxiter_, verbose_, reuse_, usesuperlu_) 975 {} 976 }; 977 978 /** \brief Linear solver backend for Restarted GMRes 979 preconditioned with ILU(0) 980 981 */ 982 983 class ISTLBackend_SEQ_GMRES_ILU0 984 : public SequentialNorm, public LinearResultStorage 985 { 986 public : 987 988 /** \brief make linear solver object 989 990 \param[in] restart_ number of iterations when GMRes has to be restarted 991 \param[in] maxiter_ maximum number of iterations to do 992 \param[in] verbose_ print messages if true 993 */ ISTLBackend_SEQ_GMRES_ILU0(int restart_=200,int maxiter_=5000,int verbose_=1)994 explicit ISTLBackend_SEQ_GMRES_ILU0(int restart_ = 200, int maxiter_ = 5000, int verbose_ = 1) 995 : restart(restart_), maxiter(maxiter_), verbose(verbose_) 996 {} 997 998 /** \brief solve the given linear system 999 1000 \param[in] A the given matrix 1001 \param[out] z the solution vector to be computed 1002 \param[in] r right hand side 1003 \param[in] reduction to be achieved 1004 */ 1005 template<class M, class V, class W> apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)1006 void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction) 1007 { 1008 using Backend::Native; 1009 using Backend::native; 1010 Dune::MatrixAdapter< 1011 Native<M>, 1012 Native<V>, 1013 Native<W> 1014 > opa(native(A)); 1015 Dune::SeqILU< 1016 Native<M>, 1017 Native<V>, 1018 Native<W> 1019 > ilu0(native(A), 1.0); 1020 Dune::RestartedGMResSolver<Native<V>> solver(opa,ilu0,reduction,restart,maxiter,verbose); 1021 Dune::InverseOperatorResult stat; 1022 solver.apply(native(z), native(r), stat); 1023 res.converged = stat.converged; 1024 res.iterations = stat.iterations; 1025 res.elapsed = stat.elapsed; 1026 res.reduction = stat.reduction; 1027 res.conv_rate = stat.conv_rate; 1028 } 1029 1030 private : 1031 int restart, maxiter, verbose; 1032 }; 1033 1034 //============================ 1035 // Matrix free solver backends 1036 //============================ 1037 1038 template <class GO> 1039 class ISTLBackend_SEQ_MatrixFree_BCGS_Richardson 1040 : public ISTLBackend_SEQ_MatrixFree_Richardson<GO, Dune::BiCGSTABSolver> 1041 { 1042 public: 1043 /*! \brief make a linear solver object 1044 \param[in] op_ Operator that will be passed to ISTL solver 1045 \param[in] maxiter_ maximum number of iterations to do 1046 \param[in] verbose_ print messages if true 1047 */ ISTLBackend_SEQ_MatrixFree_BCGS_Richardson(const GO & go_,unsigned maxiter_=5000,int verbose_=1)1048 explicit ISTLBackend_SEQ_MatrixFree_BCGS_Richardson (const GO& go_, unsigned maxiter_=5000, int verbose_=1) 1049 : ISTLBackend_SEQ_MatrixFree_Richardson<GO, Dune::BiCGSTABSolver>(go_, maxiter_, verbose_) 1050 {} 1051 }; 1052 1053 1054 //! \} group Sequential Solvers 1055 //! \} group Backend 1056 1057 } // namespace PDELab 1058 } // namespace Dune 1059 1060 #endif // DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH 1061