File: CG.h

package info (click to toggle)
lammps 20220106.git7586adbb6a%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 348,064 kB
  • sloc: cpp: 831,421; python: 24,896; xml: 14,949; f90: 10,845; ansic: 7,967; sh: 4,226; perl: 4,064; fortran: 2,424; makefile: 1,501; objc: 238; lisp: 163; csh: 16; awk: 14; tcl: 6
file content (84 lines) | stat: -rw-r--r-- 2,063 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//*****************************************************************
// Iterative template routine -- CG
//
// CG solves the symmetric positive definite linear
// system Ax=b using the Conjugate Gradient method.
//
// CG follows the algorithm described on p. 15 in the
// SIAM Templates book.
//
// The return value indicates convergence within max_iter (input)
// iterations (0), or no convergence within max_iter iterations (1).
//
// Upon successful return, output arguments have the following values:
//
//        x  --  approximate solution to Ax = b
// max_iter  --  the number of iterations performed before the
//               tolerance was reached
//      tol  --  the residual after the final iteration
//
//*****************************************************************

  /**
   *  @class  CG
   *  @brief  Base class for solving the linear system Ax=b using the Conjugate Gradient method
   */

template < class Matrix, class Vector, class DataVector, class Preconditioner, class Real >
int
CG(const Matrix &A, Vector &x, const DataVector &b, const Preconditioner &M, int &max_iter, Real &tol) {
  Real resid;
  DenseVector<Real> p, z, q;
  Real alpha, beta, rho, rho_1(0);
  DenseVector<Real> tmp;
  tmp.reset(b.size());

  p.reset(b.size());
  z.reset(b.size());
  q.reset(b.size());

  Real normb = b.norm();
  DenseVector<Real> r;
  tmp = A*x;
  r = b - tmp;
  // Implicit assumption that only diagonal matrices are being used for preconditioning
  Preconditioner Minv = M.inv();

  if (normb == 0.0)
    normb = 1;

  if ((resid = r.norm() / normb) <= tol) {
    tol = resid;
    max_iter = 0;
    return 0;
  }

  for (int i = 0; i < max_iter; i++) {
    z = Minv*r;
    rho = r.dot(z);

    if (i == 0)
      p = z;
    else {
      beta = rho / rho_1;
      tmp = p*beta;
      p = z + tmp;
    }

    q = A*p;
    alpha = rho / p.dot(q);

    x += p*alpha;
    r -= q*alpha;

    if ((resid = r.norm() / normb) <= tol)
    {
      tol = resid;
      max_iter = i+1;
      return 0;
    }
    rho_1 = rho;
  }
  tol = resid;
  return 1;
}