OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
FLUMatrix.h
Go to the documentation of this file.
1 #ifndef CLASSIC_FLUMatrix_HH
2 #define CLASSIC_FLUMatrix_HH
3 
4 // ------------------------------------------------------------------------
5 // $RCSfile: FLUMatrix.h,v $
6 // ------------------------------------------------------------------------
7 // $Revision: 1.1.1.1 $
8 // ------------------------------------------------------------------------
9 // Copyright: see Copyright.readme
10 // ------------------------------------------------------------------------
11 //
12 // Template class: FLUMatrix
13 //
14 // ------------------------------------------------------------------------
15 // Class category: FixedAlgebra
16 // ------------------------------------------------------------------------
17 //
18 // $Date: 2000/03/27 09:32:36 $
19 // $Author: fci $
20 //
21 // ------------------------------------------------------------------------
22 
23 #include "FixedAlgebra/FArray1D.h"
24 #include "FixedAlgebra/FMatrix.h"
26 #include <cmath>
27 
28 
29 // Template class FLUMatrix<T,N>
30 // ------------------------------------------------------------------------
32 // Constructed from a FMatrix<T,N,N>, this class remembers the triangular
33 // decomposition and can return the back-substitution or the inverse.
34 // When FLUMatrix is used on a complex matrix, then the statement
35 // [pre]
36 // include std::abs;
37 // [/pre]
38 // is required in the calling file, so as to inject the [tt]abs()[/tt]
39 // function to the global namespace.
40 
41 template <class T, int N>
42 class FLUMatrix {
43 
44 public:
45 
47  // Find triangel decomposition of the matrix [b]M[/b].
48  // Throw SingularMatrixError if [b]M[/b] is singular.
49  explicit FLUMatrix(const FMatrix<T, N, N> &M);
50 
51  FLUMatrix();
52  FLUMatrix(const FLUMatrix<T, N> &);
53  ~FLUMatrix();
55 
57  // Perform back substitution on the vector [b]B[/b].
58  // The new [b]B[/b] is the old [b]B[/b], premultiplied by the inverse.
59  void backSubstitute(FVector<T, N> &B) const;
60 
62  // Perform back substitution on the matrix [b]M[/b].
63  // The new [b]M[/b] is the old [b]M[/b], premultiplied by the inverse.
64  template <int M>
65  void backSubstitute(FMatrix<T, N, M> &MM) const;
66 
68  // Construct and return the inverse.
69  FMatrix<T, N, N> inverse() const;
70 
71 private:
72 
73  // Back substitution on iterator.
74  template <class Iterator>
75  void backSubstitute(Iterator) const;
76 
77  // The LU-decomposed matrix.
79 
80  // The [b]index[/b] array used for LU decomposition and back substitution.
82 };
83 
84 
85 // Template function implementation.
86 // ------------------------------------------------------------------------
87 
88 template <class T, int N>
90  decomp(), index()
91 {}
92 
93 
94 template <class T, int N>
96  decomp(rhs.decomp), index(rhs.index)
97 {}
98 
99 
100 template <class T, int N>
102  decomp(rhs), index(rhs.nrows()) {
103  // Builds the L-U decomp of the square matrix rhs.
104  // This constructor is used in combination with backSubstitute
105  // to solve linear equations or invert a matrix.
106 
107  // Scale the matrix (find largest element of each row).
108  FArray1D<double, N> scaleVector;
109  for(int i = 0; i < N; i++) {
110  double maximum = 0.0;
111 
112  for(int j = 0; j < N; j++) {
113  double temp = std::abs(decomp[i][j]);
114  if(temp > maximum) maximum = temp;
115  }
116 
117  if(maximum == 0.0) throw SingularMatrixError("FLUMatrix::FLUMatrix()");
118  scaleVector[i] = 1.0 / maximum;
119  }
120 
121  // The loop over coFLUMns of Crout's method.
122  for(int j = 0; j < N; j++) {
123  // Eqn 2.3.12 except for j = i:
124  for(int i = 0; i < j; i++) {
125  for(int k = 0; k < i; k++) {
126  decomp[i][j] -= decomp[i][k] * decomp[k][j];
127  }
128  }
129 
130  // Initialize the search for the largest pivot element.
131  double maximum = 0.0;
132  int col_max = 0;
133 
134  // i = j of eq 2.3.12 & i = j + 1 .. N of 2.3.13.
135  for(int i = j; i < N; i++) {
136  for(int k = 0; k < j; k++) {
137  decomp[i][j] -= decomp[i][k] * decomp[k][j];
138  }
139 
140  // Figure of merit for pivot.
141  double dum = std::abs(scaleVector[i] * decomp[i][j]);
142 
143  // Is it better than the best so far ?
144  if(dum >= maximum) {
145  col_max = i;
146  maximum = dum;
147  }
148  }
149 
150  // Do we need to interchange rows and the scale factor ?
151  if(j != col_max) {
152  decomp.swapRows(col_max, j);
153  std::swap(scaleVector[col_max], scaleVector[j]);
154  }
155 
156  index[j] = col_max;
157 
158  // Now, finally, divide by the pivot element.
159  if(j != N - 1) {
160  T dum = T(1) / decomp[j][j];
161  for(int i = j + 1; i < N; i++) decomp[i][j] *= dum;
162  }
163  }
164 }
165 
166 template <class T, int N>
168 {}
169 
170 
171 template <class T, int N>
173  decomp = rhs.decomp;
174  index = rhs.index;
175  return *this;
176 }
177 
178 
179 template <class T, int N> template <class I> inline
181  // Solves the set of N linear equations A*X = B.
182  // Here "this" is the LU-decomp of the matrix A, determined by the
183  // routine LUDecompose().
184  // B is input as the rhs vector B, and returns with the solution vector X.
185  // This routine takes into account the possibility that B will begin with
186  // many zero elements, so it is efficient for use in matrix inversion.
187  // See pp 36-37 in Press & Flannery.
188 
189  int ii = - 1;
190 
191  for(int i = 0; i < N; i++) {
192  int ip = index[i];
193  T sum = iter[ip];
194  iter[ip] = iter[i];
195 
196  if(ii >= 0) {
197  for(int j = ii; j < i; j++) {
198  sum -= decomp[i][j] * iter[j];
199  }
200  } else if(sum != T(0)) {
201  ii = i;
202  }
203 
204  iter[i] = sum;
205  }
206 
207  for(int i = N; i > 0;) {
208  i--;
209  T sum = iter[i];
210 
211  for(int j = i + 1; j < N; j++) {
212  sum -= decomp[i][j] * iter[j];
213  }
214 
215  // store a component of the solution vector X.
216  iter[i] = sum / decomp[i][i];
217  }
218 }
219 
220 
221 template <class T, int N>
223  backSubstitute(B.begin());
224 }
225 
226 
227 template <class T, int N> template <int M>
229  for(int column = 0; column < M; column++) {
230  backSubstitute(matrix.col_begin(column));
231  }
232 }
233 
234 
235 template <class T, int N>
237  FMatrix<T, N, N> result;
238  result = result + T(1);
239  backSubstitute(result);
240  return result;
241 }
242 
243 #endif // CLASSIC_FLUMatrix_HH
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Definition: rbendmap.h:8
FLUMatrix< T, N > & operator=(const FLUMatrix &)
Definition: FLUMatrix.h:172
A templated representation for vectors.
Definition: PartBunchBase.h:26
iterator begin()
Get iterator pointing to beginning of array.
Definition: FArray1D.h:192
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1213
FMatrix< T, N, N > decomp
Definition: FLUMatrix.h:78
Singular matrix exception.
~FLUMatrix()
Definition: FLUMatrix.h:167
A templated representation of a LU-decomposition.
Definition: FLUMatrix.h:42
col_iterator col_begin(int c)
Get column iterator.
void backSubstitute(FVector< T, N > &B) const
Back substitution.
Definition: FLUMatrix.h:222
FLUMatrix()
Definition: FLUMatrix.h:89
void swapRows(int r1, int r2)
Exchange rows.
Definition: FArray2D.h:409
FMatrix< T, N, N > inverse() const
Get inverse.
Definition: FLUMatrix.h:236
FArray1D< int, N > index
Definition: FLUMatrix.h:81