SND@LHC Software
Loading...
Searching...
No Matches
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
11namespace gbl {
12
14BorderedBandMatrix::BorderedBandMatrix() : numSize(0), numBorder(0), numBand(0), numCol(0) {
15}
16
19
21
26void 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
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;
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
212VVector 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
241VMatrix 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}
VMatrix theMixed
Mixed part.
void printMatrix() const
Print bordered band matrix.
void decomposeBand()
(root free) Cholesky decomposition of band part: C=LDL^T
VSymMatrix theBorder
Border part.
unsigned int numBand
Band width.
VVector solveBand(const VVector &aRightHandSide) const
Solve for band part.
unsigned int numCol
Band matrix size.
BorderedBandMatrix()
Create bordered band matrix.
VMatrix bandOfAVAT(const VMatrix &anArray, const VSymMatrix &aSymArray) const
Calculate band part of: 'anArray * aSymArray * anArray.T'.
VMatrix invertBand()
Invert band part.
unsigned int numBorder
Border size.
void resize(unsigned int nSize, unsigned int nBorder=1, unsigned int nBand=5)
Resize bordered band matrix.
void solveAndInvertBorderedBand(const VVector &aRightHandSide, VVector &aSolution)
Solve linear equation system, partially calculate inverse.
unsigned int numSize
Matrix size.
void addBlockMatrix(double aWeight, const std::vector< unsigned int > *anIndex, const std::vector< double > *aVector)
Add symmetric block matrix.
TMatrixDSym getBlockMatrix(const std::vector< unsigned int > anIndex) const
Retrieve symmetric block matrix.
Simple Matrix based on std::vector<double>
Definition VMatrix.h:42
unsigned int getNumCols() const
Get number of columns.
Definition VMatrix.cc:65
VMatrix transpose() const
Get transposed matrix.
Definition VMatrix.cc:43
unsigned int getNumRows() const
Get number of rows.
Definition VMatrix.cc:57
void resize(const unsigned int nRows, const unsigned int nCols)
Resize Matrix.
Definition VMatrix.cc:33
void print() const
Print matrix.
Definition VMatrix.cc:70
Simple symmetric Matrix based on std::vector<double>
Definition VMatrix.h:65
void print() const
Print matrix.
Definition VMatrix.cc:167
unsigned int invert()
Matrix inversion.
Definition VMatrix.cc:326
void resize(const unsigned int nRows)
Resize symmetric matrix.
Definition VMatrix.cc:153
Simple Vector based on std::vector<double>
Definition VMatrix.h:22
void putVec(const VVector &aVector, unsigned int start=0)
Put part of vector.
Definition VMatrix.cc:262
VVector getVec(unsigned int len, unsigned int start=0) const
Get part of vector.
Definition VMatrix.cc:251
Namespace for the general broken lines package.