CHROMA
lu_solve.cc
Go to the documentation of this file.
1 #include "chromabase.h"
3 
4 namespace Chroma
5 {
6  // Solve M a = b by LU decomposition with partial pivoting
7  //
8  void LUSolve( multi1d<DComplex>& a,
9  const multi2d<DComplex>& M,
10  const multi1d<DComplex>& b )
11  {
12  START_CODE();
13 
14  int Nvec1 = M.size1();
15  int Nvec2 = M.size2();
16 
17  if( Nvec1 != Nvec2 ) {
18  QDPIO::cerr << "Barf" << std::endl;
19  QDP_abort(1);
20  }
21 
22  int Nvec = Nvec1;
23 
24  // Copy b and M so that we can change elements of the copies
25  // during the pivoting and the LU decomposition. We can save
26  // memory by just destroying M, but we never really expect
27  // it to be really big: At most 20x20 I should imagine.
28 
29  multi1d<DComplex> b_local(b);
30  multi2d<DComplex> M_local(M);
31 
32  // -----------------------------------------------------------------
33  // LU Decompose M_local, in place (Crone's algorithm?)
34  // It's in Numerical Recipes but also a more understandable
35  // description can be found at:
36  // http://csep10.phys.utk.edu/guidry/
37  // phys594/lectures/linear_algebra/lanotes/node3.html
38  //
39  // OR look in your favourite Matrix Analysis text
40  // -----------------------------------------------------------------
41 
42  // -------------------------------------------------------------
43  // Start LU Decomp. Definition. 0-th row of U is 0-th row of M
44  // and L_{i,i} = 1 for all i
45  //
46  // So we start with the 1-th (2nd) row
47  // ------------------------------------------------------------
48 
49  for(int i = 1; i < Nvec; i++) {
50 
51  // ------------------------------------------------------------
52  // Parital Pivot: Find the row with the largest element in the
53  // ith-column and make that the i-th row. This swaps rows.
54  // so I don't need to reorder the unknowns, but I do need
55  // to reorder the b_local
56  // ------------------------------------------------------------
57  Double maxnorm = norm2(M_local(i,i));
58  int maxrow = i;
59 
60  // Compare norms with other elements in column j for row i+1.N
61  for(int row=i+1; row < Nvec; row++) {
62  if ( toBool( norm2(M_local(row,i)) > maxnorm ) ) {
63  // Norm of M_local(j,i) is bigger, store it as the maximum
64  // and store its index
65  maxnorm = norm2(M_local(row,i));
66  maxrow = row;
67  }
68  }
69 
70  // If the element with maximum norm is not in row i, swap
71  // its row with row i
72  if( maxrow != i ) {
73 
74  DComplex tmp;
75 
76  // Swap rows i and maxindex
77  for(int j=0; j < Nvec; j++ ) {
78  tmp = M_local(i, j);
79  M_local(i,j) = M_local(maxrow, j);
80  M_local(maxrow, j) = tmp;
81  }
82 
83  // Swap elems of b
84  tmp = b_local[i];
85  b_local[i] = b_local[maxrow];
86  b_local[maxrow] = tmp;
87  }
88 
89  // --------------------------------------------------------
90  // End of pivoting code
91  // --------------------------------------------------------
92 
93 
94  // --------------------------------------------------------
95  // Work out elements of L & U in place in M_local for row i
96  // --------------------------------------------------------
97  for(int j=0; j < i; j++) {
98 
99  DComplex sum_LU = DComplex(0);;
100  for(int k = 0; k < j; k++) {
101  sum_LU += M_local(i,k)*M_local(k,j);
102  }
103 
104  M_local(i,j) -= sum_LU;
105  M_local(i,j) /= M_local(j,j);
106  }
107 
108  for(int j=i; j < Nvec; j++) {
109  DComplex sum_LU = DComplex(0);
110  for(int k = 0; k < i; k++) {
111  sum_LU += M_local(i,k)*M_local(k,j);
112  }
113  M_local(i,j) -= sum_LU;
114  }
115 
116  }
117 
118  // ----------------------------------------------------
119  // LU Decomp finished. M_local now holds the
120  // U matrix in its diagonal and superdiagonal elements
121  // and the subdiagonal elements of the L matrix in its
122  // subdiagonal. Recall that the Diagonal elements of L
123  // are chosen to be 1
124  // -----------------------------------------------------
125 
126  // Solve L y = b by forward substitution
127  multi1d<DComplex> y(Nvec);
128 
129  y[0] = b[0];
130  for(int i=1; i < Nvec; i++) {
131  y[i] = b_local[i];
132  for(int j=0; j < i; j++) {
133  y[i] -= M_local(i,j)*y[j];
134  }
135  }
136 
137  // Solve U a = y by back substitution
138  a[Nvec-1] = y[Nvec-1] / M_local(Nvec-1, Nvec-1);
139 
140  for(int i = Nvec-2; i >= 0; i--) {
141  DComplex tmpcmpx = y[i];
142  for(int j=i+1; j < Nvec; j++) {
143  tmpcmpx -= M_local(i,j)*a[j];
144  }
145  a[i] = tmpcmpx/M_local(i,i);
146  }
147 
148  END_CODE();
149  }
150 
151 
152 } // End Namespace
Primary include file for CHROMA library code.
void LUSolve(multi1d< DComplex > &a, const multi2d< DComplex > &M, const multi1d< DComplex > &b)
Solve M a = b by LU decomposition with partial pivoting.
Definition: lu_solve.cc:8
unsigned j
Definition: ldumul_w.cc:35
LU solver.
int y
Definition: meslate.cc:35
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LatticeFermion tmp
Definition: mespbg5p_w.cc:36
int i
Definition: pbg5p_w.cc:55
Complex a
Definition: invbicg.cc:95
START_CODE()
Complex b
Definition: invbicg.cc:96
int k
Definition: invbicg.cc:119
FloatingPoint< double > Double
Definition: gtest.h:7351