Reference documentation for deal.II version 8.4.2
solver_cg.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii__solver_cg_h
17 #define dealii__solver_cg_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/lac/tridiagonal_matrix.h>
22 #include <deal.II/lac/solver.h>
23 #include <deal.II/lac/solver_control.h>
24 #include <deal.II/base/exceptions.h>
25 #include <deal.II/base/logstream.h>
26 #include <deal.II/base/subscriptor.h>
27 #include <cmath>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 // forward declaration
33 
34 
37 
98 template <typename VectorType = Vector<double> >
99 class SolverCG : public Solver<VectorType>
100 {
101 public:
106 
111  {
117 
124 
131 
138 
144  explicit
145  AdditionalData (const bool log_coefficients,
146  const bool compute_condition_number = false,
147  const bool compute_all_condition_numbers = false,
148  const bool compute_eigenvalues = false) DEAL_II_DEPRECATED;
149 
153  AdditionalData();
154  };
155 
159  SolverCG (SolverControl &cn,
160  VectorMemory<VectorType> &mem,
161  const AdditionalData &data = AdditionalData());
162 
167  SolverCG (SolverControl &cn,
168  const AdditionalData &data=AdditionalData());
169 
173  virtual ~SolverCG ();
174 
178  template <typename MatrixType, typename PreconditionerType>
179  void
180  solve (const MatrixType &A,
181  VectorType &x,
182  const VectorType &b,
183  const PreconditionerType &precondition);
184 
191  boost::signals2::connection
193  const std_cxx11::function<void (double,double)> &slot);
194 
201  boost::signals2::connection
202  connect_condition_number_slot(const std_cxx11::function<void (double)> &slot,
203  const bool every_iteration=false);
204 
211  boost::signals2::connection
213  const std_cxx11::function<void (const std::vector<double> &)> &slot,
214  const bool every_iteration=false);
215 
216 protected:
221  virtual double criterion();
222 
228  virtual void print_vectors(const unsigned int step,
229  const VectorType &x,
230  const VectorType &r,
231  const VectorType &d) const;
232 
240  static void
242  const std::vector<double> &diagonal,
243  const std::vector<double> &offdiagonal,
244  const boost::signals2::signal<void (const std::vector<double> &)> &eigenvalues_signal,
245  const boost::signals2::signal<void (double)> &cond_signal,
246  const bool log_eigenvalues,
247  const bool log_cond);
248 
253  VectorType *Vr;
254  VectorType *Vp;
255  VectorType *Vz;
256 
263  double res2;
264 
268  AdditionalData additional_data;
269 
273  boost::signals2::signal<void (double,double)> coefficients_signal;
274 
279  boost::signals2::signal<void (double)> condition_number_signal;
280 
285  boost::signals2::signal<void (double)> all_condition_numbers_signal;
286 
291  boost::signals2::signal<void (const std::vector<double> &)> eigenvalues_signal;
292 
297  boost::signals2::signal<void (const std::vector<double> &)> all_eigenvalues_signal;
298 
299 private:
300  void cleanup();
301 };
302 
305 /*------------------------- Implementation ----------------------------*/
306 
307 #ifndef DOXYGEN
308 
309 template <typename VectorType>
310 inline
312 AdditionalData (const bool log_coefficients,
313  const bool compute_condition_number,
314  const bool compute_all_condition_numbers,
315  const bool compute_eigenvalues)
316  :
317  log_coefficients (log_coefficients),
318  compute_condition_number(compute_condition_number),
319  compute_all_condition_numbers(compute_all_condition_numbers),
320  compute_eigenvalues(compute_eigenvalues)
321 {}
322 
323 
324 
325 template <typename VectorType>
326 inline
329  :
330  log_coefficients (false),
331  compute_condition_number(false),
332  compute_all_condition_numbers(false),
333  compute_eigenvalues(false)
334 {}
335 
336 
337 
338 template <typename VectorType>
341  const AdditionalData &data)
342  :
343  Solver<VectorType>(cn,mem),
344  additional_data(data)
345 {}
346 
347 
348 
349 template <typename VectorType>
351  const AdditionalData &data)
352  :
353  Solver<VectorType>(cn),
354  additional_data(data)
355 {}
356 
357 
358 
359 template <typename VectorType>
361 {}
362 
363 
364 
365 template <typename VectorType>
366 double
368 {
369  return std::sqrt(res2);
370 }
371 
372 
373 
374 template <typename VectorType>
375 void
377 {
378  this->memory.free(Vr);
379  this->memory.free(Vp);
380  this->memory.free(Vz);
381  deallog.pop();
382 }
383 
384 
385 
386 template <typename VectorType>
387 void
388 SolverCG<VectorType>::print_vectors(const unsigned int,
389  const VectorType &,
390  const VectorType &,
391  const VectorType &) const
392 {}
393 
394 
395 
396 template <typename VectorType>
397 inline void
399 (const std::vector<double> &diagonal,
400  const std::vector<double> &offdiagonal,
401  const boost::signals2::signal<void (const std::vector<double> &)> &eigenvalues_signal,
402  const boost::signals2::signal<void (double)> &cond_signal,
403  const bool log_eigenvalues,
404  const bool log_cond)
405 {
406  //Avoid computing eigenvalues unless they are needed.
407  if (!cond_signal.empty()|| !eigenvalues_signal.empty() || log_cond ||
408  log_eigenvalues)
409  {
410  TridiagonalMatrix<double> T(diagonal.size(), true);
411  for (size_type i=0; i<diagonal.size(); ++i)
412  {
413  T(i,i) = diagonal[i];
414  if (i< diagonal.size()-1)
415  T(i,i+1) = offdiagonal[i];
416  }
417  T.compute_eigenvalues();
418  //Need two eigenvalues to estimate the condition number.
419  if (diagonal.size()>1)
420  {
421  double condition_number=T.eigenvalue(T.n()-1)/T.eigenvalue(0);
422  cond_signal(condition_number);
423  //Send to deallog
424  if (log_cond)
425  {
426  deallog << "Condition number estimate: " <<
427  condition_number << std::endl;
428  }
429  }
430  //Avoid copying the eigenvalues of T to a vector unless a signal is
431  //connected.
432  if (!eigenvalues_signal.empty())
433  {
434  std::vector<double> eigenvalues(T.n());
435  for (unsigned int j = 0; j < T.n(); ++j)
436  {
437  eigenvalues.at(j)=T.eigenvalue(j);
438  }
439  eigenvalues_signal(eigenvalues);
440  }
441  if (log_eigenvalues)
442  {
443  for (size_type i=0; i<T.n(); ++i)
444  deallog << ' ' << T.eigenvalue(i);
445  deallog << std::endl;
446  }
447  }
448 
449 }
450 
451 
452 
453 template <typename VectorType>
454 template <typename MatrixType, typename PreconditionerType>
455 void
456 SolverCG<VectorType>::solve (const MatrixType &A,
457  VectorType &x,
458  const VectorType &b,
459  const PreconditionerType &precondition)
460 {
462 
463  deallog.push("cg");
464 
465  // Memory allocation
466  Vr = this->memory.alloc();
467  Vz = this->memory.alloc();
468  Vp = this->memory.alloc();
469  // Should we build the matrix for
470  // eigenvalue computations?
471  const bool do_eigenvalues = !condition_number_signal.empty()
472  |!all_condition_numbers_signal.empty()
473  |!eigenvalues_signal.empty()
474  |!all_eigenvalues_signal.empty()
475  | additional_data.compute_condition_number
476  | additional_data.compute_all_condition_numbers
477  | additional_data.compute_eigenvalues;
478  double eigen_beta_alpha = 0;
479 
480  // vectors used for eigenvalue
481  // computations
482  std::vector<double> diagonal;
483  std::vector<double> offdiagonal;
484 
485  int it=0;
486  double res = -std::numeric_limits<double>::max();
487 
488  try
489  {
490  // define some aliases for simpler access
491  VectorType &g = *Vr;
492  VectorType &d = *Vz;
493  VectorType &h = *Vp;
494  // resize the vectors, but do not set
495  // the values since they'd be overwritten
496  // soon anyway.
497  g.reinit(x, true);
498  d.reinit(x, true);
499  h.reinit(x, true);
500 
501  double gh,alpha,beta;
502 
503  // compute residual. if vector is
504  // zero, then short-circuit the
505  // full computation
506  if (!x.all_zero())
507  {
508  A.vmult(g,x);
509  g.add(-1.,b);
510  }
511  else
512  g.equ(-1.,b);
513  res = g.l2_norm();
514 
515  conv = this->iteration_status(0, res, x);
516  if (conv != SolverControl::iterate)
517  {
518  cleanup();
519  return;
520  }
521 
523  {
524  precondition.vmult(h,g);
525 
526  d.equ(-1.,h);
527 
528  gh = g*h;
529  }
530  else
531  {
532  d.equ(-1.,g);
533  gh = res*res;
534  }
535 
536  while (conv == SolverControl::iterate)
537  {
538  it++;
539  A.vmult(h,d);
540 
541  alpha = d*h;
542  Assert(alpha != 0., ExcDivideByZero());
543  alpha = gh/alpha;
544 
545  x.add(alpha,d);
546  res = std::sqrt(g.add_and_dot(alpha, h, g));
547 
548  print_vectors(it, x, g, d);
549 
550  conv = this->iteration_status(it, res, x);
551  if (conv != SolverControl::iterate)
552  break;
553 
555  == false)
556  {
557  precondition.vmult(h,g);
558 
559  beta = gh;
560  Assert(beta != 0., ExcDivideByZero());
561  gh = g*h;
562  beta = gh/beta;
563  d.sadd(beta,-1.,h);
564  }
565  else
566  {
567  beta = gh;
568  gh = res*res;
569  beta = gh/beta;
570  d.sadd(beta,-1.,g);
571  }
572 
573  this->coefficients_signal(alpha,beta);
574  if (additional_data.log_coefficients)
575  deallog << "alpha-beta:" << alpha << '\t' << beta << std::endl;
576  // set up the vectors
577  // containing the diagonal
578  // and the off diagonal of
579  // the projected matrix.
580  if (do_eigenvalues)
581  {
582  diagonal.push_back(1./alpha + eigen_beta_alpha);
583  eigen_beta_alpha = beta/alpha;
584  offdiagonal.push_back(std::sqrt(beta)/alpha);
585  }
586  compute_eigs_and_cond(diagonal,offdiagonal,all_eigenvalues_signal,
587  all_condition_numbers_signal,false,
588  additional_data.compute_all_condition_numbers);
589  }
590  }
591  catch (...)
592  {
593  cleanup();
594  throw;
595  }
596  compute_eigs_and_cond(diagonal,offdiagonal,eigenvalues_signal,
597  condition_number_signal,
598  additional_data.compute_eigenvalues,
599  (additional_data.compute_condition_number &&
600  !additional_data.compute_all_condition_numbers));
601 
602  // Deallocate Memory
603  cleanup();
604  // in case of failure: throw exception
605  if (conv != SolverControl::success)
606  AssertThrow(false, SolverControl::NoConvergence (it, res));
607  // otherwise exit as normal
608 }
609 
610 
611 
612 template<typename VectorType>
613 boost::signals2::connection
615 (const std_cxx11::function<void(double,double)> &slot)
616 {
617  return coefficients_signal.connect(slot);
618 }
619 
620 
621 
622 template<typename VectorType>
623 boost::signals2::connection
625 (const std_cxx11::function<void(double)> &slot,
626  const bool every_iteration)
627 {
628  if (every_iteration)
629  {
630  return all_condition_numbers_signal.connect(slot);
631  }
632  else
633  {
634  return condition_number_signal.connect(slot);
635  }
636 }
637 
638 
639 
640 template<typename VectorType>
641 boost::signals2::connection
643 (const std_cxx11::function<void (const std::vector<double> &)> &slot,
644  const bool every_iteration)
645 {
646  if (every_iteration)
647  {
648  return all_eigenvalues_signal.connect(slot);
649  }
650  else
651  {
652  return eigenvalues_signal.connect(slot);
653  }
654 }
655 
656 
657 
658 #endif // DOXYGEN
659 
660 DEAL_II_NAMESPACE_CLOSE
661 
662 #endif
boost::signals2::signal< void(double, double)> coefficients_signal
Definition: solver_cg.h:273
void pop()
Definition: logstream.cc:300
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &precondition)
static void compute_eigs_and_cond(const std::vector< double > &diagonal, const std::vector< double > &offdiagonal, const boost::signals2::signal< void(const std::vector< double > &)> &eigenvalues_signal, const boost::signals2::signal< void(double)> &cond_signal, const bool log_eigenvalues, const bool log_cond)
virtual ~SolverCG()
boost::signals2::signal< void(double)> condition_number_signal
Definition: solver_cg.h:279
SolverCG(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Continue iteration.
boost::signals2::connection connect_eigenvalues_slot(const std_cxx11::function< void(const std::vector< double > &)> &slot, const bool every_iteration=false)
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
boost::signals2::signal< void(const std::vector< double > &)> eigenvalues_signal
Definition: solver_cg.h:291
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
double res2
Definition: solver_cg.h:263
BlockDynamicSparsityPattern BlockCompressedSparsityPattern DEAL_II_DEPRECATED
unsigned int global_dof_index
Definition: types.h:88
Stop iteration, goal reached.
#define Assert(cond, exc)
Definition: exceptions.h:294
AdditionalData additional_data
Definition: solver_cg.h:268
virtual double criterion()
VectorMemory< VectorType > & memory
Definition: solver.h:402
boost::signals2::signal< SolverControl::State(const unsigned int iteration, const double check_value, const VectorType &current_iterate), StateCombiner > iteration_status
Definition: solver.h:448
Definition: solver.h:325
boost::signals2::signal< void(double)> all_condition_numbers_signal
Definition: solver_cg.h:285
void push(const std::string &text)
Definition: logstream.cc:288
VectorType * Vr
Definition: solver_cg.h:253
boost::signals2::connection connect_condition_number_slot(const std_cxx11::function< void(double)> &slot, const bool every_iteration=false)
boost::signals2::signal< void(const std::vector< double > &)> all_eigenvalues_signal
Definition: solver_cg.h:297
boost::signals2::connection connect_coefficients_slot(const std_cxx11::function< void(double, double)> &slot)
types::global_dof_index size_type
Definition: solver_cg.h:105