test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
BorderedBandMatrix.cc
Go to the documentation of this file.
1 /*
2  * BorderedBandMatrix.cpp
3  *
4  * Created on: Aug 14, 2011
5  * Author: kleinwrt
6  */
7 
9 
11 namespace gbl {
12 
14 BorderedBandMatrix::BorderedBandMatrix() : numSize(0), numBorder(0), numBand(0), numCol(0) {
15 }
16 
18 }
19 
21 
26 void BorderedBandMatrix::resize(unsigned int nSize, unsigned int nBorder,
27  unsigned int nBand) {
28  numSize = nSize;
29  numBorder = nBorder;
30  numCol = nSize - nBorder;
31  numBand = 0;
34  theBand.resize((nBand + 1), numCol);
35 }
36 
38 
47  const std::vector<unsigned int>* anIndex,
48  const std::vector<double>* aVector) {
49  int nBorder = numBorder;
50  for (unsigned int i = 0; i < anIndex->size(); ++i) {
51  int iIndex = (*anIndex)[i] - 1; // anIndex has to be sorted
52  for (unsigned int j = 0; j <= i; ++j) {
53  int jIndex = (*anIndex)[j] - 1;
54  if (iIndex < nBorder) {
55  theBorder(iIndex, jIndex) += (*aVector)[i] * aWeight
56  * (*aVector)[j];
57  } else if (jIndex < nBorder) {
58  theMixed(jIndex, iIndex - nBorder) += (*aVector)[i] * aWeight
59  * (*aVector)[j];
60  } else {
61  unsigned int nBand = iIndex - jIndex;
62  theBand(nBand, jIndex - nBorder) += (*aVector)[i] * aWeight
63  * (*aVector)[j];
64  numBand = std::max(numBand, nBand); // update band width
65  }
66  }
67  }
68 }
69 
71 
76  const std::vector<unsigned int> anIndex) const {
77 
78  TMatrixDSym aMatrix(anIndex.size());
79  int nBorder = numBorder;
80  for (unsigned int i = 0; i < anIndex.size(); ++i) {
81  int iIndex = anIndex[i] - 1; // anIndex has to be sorted
82  for (unsigned int j = 0; j <= i; ++j) {
83  int jIndex = anIndex[j] - 1;
84  if (iIndex < nBorder) {
85  aMatrix(i, j) = theBorder(iIndex, jIndex); // border part of inverse
86  } else if (jIndex < nBorder) {
87  aMatrix(i, j) = -theMixed(jIndex, iIndex - nBorder); // mixed part of inverse
88  } else {
89  unsigned int nBand = iIndex - jIndex;
90  aMatrix(i, j) = theBand(nBand, jIndex - nBorder); // band part of inverse
91  }
92  aMatrix(j, i) = aMatrix(i, j);
93  }
94  }
95  return aMatrix;
96 }
97 
99 
126  const VVector &aRightHandSide, VVector &aSolution) {
127 
128  // decompose band
129  decomposeBand();
130  // invert band
131  VMatrix inverseBand = invertBand();
132  if (numBorder > 0) { // need to use block matrix decomposition to solve
133  // solve for mixed part
134  const VMatrix auxMat = solveBand(theMixed); // = Xt
135  const VMatrix auxMatT = auxMat.transpose(); // = X
136  // solve for border part
137  const VVector auxVec = aRightHandSide.getVec(numBorder)
138  - auxMat * aRightHandSide.getVec(numCol, numBorder); // = b1 - Xt*b2
139  VSymMatrix inverseBorder = theBorder - theMixed * auxMatT;
140  inverseBorder.invert(); // = E
141  const VVector borderSolution = inverseBorder * auxVec; // = x1
142  // solve for band part
143  const VVector bandSolution = solveBand(
144  aRightHandSide.getVec(numCol, numBorder)); // = x
145  aSolution.putVec(borderSolution);
146  aSolution.putVec(bandSolution - auxMatT * borderSolution, numBorder); // = x2
147  // parts of inverse
148  theBorder = inverseBorder; // E
149  theMixed = inverseBorder * auxMat; // E*Xt (-mixed part of inverse) !!!
150  theBand = inverseBand + bandOfAVAT(auxMatT, inverseBorder); // band(D^-1 + X*E*Xt)
151  } else {
152  aSolution.putVec(solveBand(aRightHandSide));
153  theBand = inverseBand;
154  }
155 }
156 
159  std::cout << "Border part " << std::endl;
160  theBorder.print();
161  std::cout << "Mixed part " << std::endl;
162  theMixed.print();
163  std::cout << "Band part " << std::endl;
164  theBand.print();
165 }
166 
167 /*============================================================================
168  from Dbandmatrix.F (MillePede-II by V. Blobel, Univ. Hamburg)
169  ============================================================================*/
171 
178 
179  int nRow = numBand + 1;
180  int nCol = numCol;
181  VVector auxVec(nCol);
182  for (int i = 0; i < nCol; ++i) {
183  auxVec(i) = theBand(0, i) * 16.0; // save diagonal elements
184  }
185  for (int i = 0; i < nCol; ++i) {
186  if ((theBand(0, i) + auxVec(i)) != theBand(0, i)) {
187  theBand(0, i) = 1.0 / theBand(0, i);
188  if (theBand(0, i) < 0.) {
189  throw 3; // not positive definite
190  }
191  } else {
192  theBand(0, i) = 0.0;
193  throw 2; // singular
194  }
195  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
196  double rxw = theBand(j, i) * theBand(0, i);
197  for (int k = 0; k < std::min(nRow, nCol - i) - j; ++k) {
198  theBand(k, i + j) -= theBand(k + j, i) * rxw;
199  }
200  theBand(j, i) = rxw;
201  }
202  }
203 }
204 
206 
212 VVector BorderedBandMatrix::solveBand(const VVector &aRightHandSide) const {
213 
214  int nRow = theBand.getNumRows();
215  int nCol = theBand.getNumCols();
216  VVector aSolution(aRightHandSide);
217  for (int i = 0; i < nCol; ++i) // forward substitution
218  {
219  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
220  aSolution(j + i) -= theBand(j, i) * aSolution(i);
221  }
222  }
223  for (int i = nCol - 1; i >= 0; i--) // backward substitution
224  {
225  double rxw = theBand(0, i) * aSolution(i);
226  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
227  rxw -= theBand(j, i) * aSolution(j + i);
228  }
229  aSolution(i) = rxw;
230  }
231  return aSolution;
232 }
233 
235 
241 VMatrix BorderedBandMatrix::solveBand(const VMatrix &aRightHandSide) const {
242 
243  int nRow = theBand.getNumRows();
244  int nCol = theBand.getNumCols();
245  VMatrix aSolution(aRightHandSide);
246  for (unsigned int iBorder = 0; iBorder < numBorder; iBorder++) {
247  for (int i = 0; i < nCol; ++i) // forward substitution
248  {
249  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
250  aSolution(iBorder, j + i) -= theBand(j, i)
251  * aSolution(iBorder, i);
252  }
253  }
254  for (int i = nCol - 1; i >= 0; i--) // backward substitution
255  {
256  double rxw = theBand(0, i) * aSolution(iBorder, i);
257  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
258  rxw -= theBand(j, i) * aSolution(iBorder, j + i);
259  }
260  aSolution(iBorder, i) = rxw;
261  }
262  }
263  return aSolution;
264 }
265 
267 
271 
272  int nRow = numBand + 1;
273  int nCol = numCol;
274  VMatrix inverseBand(nRow, nCol);
275 
276  for (int i = nCol - 1; i >= 0; i--) {
277  double rxw = theBand(0, i);
278  for (int j = i; j >= std::max(0, i - nRow + 1); j--) {
279  for (int k = j + 1; k < std::min(nCol, j + nRow); ++k) {
280  rxw -= inverseBand(abs(i - k), std::min(i, k))
281  * theBand(k - j, j);
282  }
283  inverseBand(i - j, j) = rxw;
284  rxw = 0.;
285  }
286  }
287  return inverseBand;
288 }
289 
291 
295  const VSymMatrix &aSymArray) const {
296  int nBand = numBand;
297  int nCol = numCol;
298  int nBorder = numBorder;
299  double sum;
300  VMatrix aBand((nBand + 1), nCol);
301  for (int i = 0; i < nCol; ++i) {
302  for (int j = std::max(0, i - nBand); j <= i; ++j) {
303  sum = 0.;
304  for (int l = 0; l < nBorder; ++l) { // diagonal
305  sum += anArray(i, l) * aSymArray(l, l) * anArray(j, l);
306  for (int k = 0; k < l; ++k) { // off diagonal
307  sum += anArray(i, l) * aSymArray(l, k) * anArray(j, k)
308  + anArray(i, k) * aSymArray(l, k) * anArray(j, l);
309  }
310  }
311  aBand(i - j, j) = sum;
312  }
313  }
314  return aBand;
315 }
316 
317 }
void printMatrix() const
Print bordered band matrix.
VVector getVec(unsigned int len, unsigned int start=0) const
Get part of vector.
Definition: VMatrix.cc:251
void addBlockMatrix(double aWeight, const std::vector< unsigned int > *anIndex, const std::vector< double > *aVector)
Add symmetric block matrix.
int i
Definition: DBlmapReader.cc:9
void print() const
Print matrix.
Definition: VMatrix.cc:167
unsigned int getNumRows() const
Get number of rows.
Definition: VMatrix.cc:57
Simple Matrix based on std::vector&lt;double&gt;
Definition: VMatrix.h:41
unsigned int invert()
Matrix inversion.
Definition: VMatrix.cc:326
BorderedBandMatrix()
Create bordered band matrix.
void putVec(const VVector &aVector, unsigned int start=0)
Put part of vector.
Definition: VMatrix.cc:262
void resize(const unsigned int nRows, const unsigned int nCols)
Resize Matrix.
Definition: VMatrix.cc:33
unsigned int numCol
Band matrix size.
void resize(const unsigned int nRows)
Resize symmetric matrix.
Definition: VMatrix.cc:153
VMatrix transpose() const
Get transposed matrix.
Definition: VMatrix.cc:43
VMatrix invertBand()
Invert band part.
VMatrix theMixed
Mixed part.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
void decomposeBand()
(root free) Cholesky decomposition of band part: C=LDL^T
unsigned int numBorder
Border size.
T min(T a, T b)
Definition: MathUtil.h:58
Simple symmetric Matrix based on std::vector&lt;double&gt;
Definition: VMatrix.h:64
VSymMatrix theBorder
Border part.
void print() const
Print matrix.
Definition: VMatrix.cc:70
unsigned int getNumCols() const
Get number of columns.
Definition: VMatrix.cc:65
void resize(unsigned int nSize, unsigned int nBorder=1, unsigned int nBand=5)
Resize bordered band matrix.
VMatrix theBand
Band part.
VMatrix bandOfAVAT(const VMatrix &anArray, const VSymMatrix &aSymArray) const
Calculate band part of: &#39;anArray * aSymArray * anArray.T&#39;.
Simple Vector based on std::vector&lt;double&gt;
Definition: VMatrix.h:21
TMatrixDSym getBlockMatrix(const std::vector< unsigned int > anIndex) const
Retrieve symmetric block matrix.
tuple cout
Definition: gather_cfg.py:145
unsigned int numSize
Matrix size.
VVector solveBand(const VVector &aRightHandSide) const
Solve for band part.
void solveAndInvertBorderedBand(const VVector &aRightHandSide, VVector &aSolution)
Solve linear equation system, partially calculate inverse.
unsigned int numBand
Band width.