Project
Loading...
Searching...
No Matches
MinResSolve.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <iomanip>
15#include <TMath.h>
16#include <TStopwatch.h>
17
18#include "Framework/Logger.h"
23
24using namespace o2::fwdalign;
25
27
28//______________________________________________________
30 : fSize(0),
31 fPrecon(0),
32 fMatrix(nullptr),
33 fRHS(nullptr),
34 fPVecY(nullptr),
35 fPVecR1(nullptr),
36 fPVecR2(nullptr),
37 fPVecV(nullptr),
38 fPVecW(nullptr),
39 fPVecW1(nullptr),
40 fPVecW2(nullptr),
41 fPvv(nullptr),
42 fPvz(nullptr),
43 fPhh(nullptr),
44 fDiagLU(nullptr),
45 fMatL(nullptr),
46 fMatU(nullptr),
47 fMatBD(nullptr)
48{
49}
50
51//______________________________________________________
53 : TObject(src),
54 fSize(src.fSize),
55 fPrecon(src.fPrecon),
56 fMatrix(src.fMatrix),
57 fRHS(src.fRHS),
58 fPVecY(nullptr),
59 fPVecR1(nullptr),
60 fPVecR2(nullptr),
61 fPVecV(nullptr),
62 fPVecW(nullptr),
63 fPVecW1(nullptr),
64 fPVecW2(nullptr),
65 fPvv(nullptr),
66 fPvz(nullptr),
67 fPhh(nullptr),
68 fDiagLU(nullptr),
69 fMatL(nullptr),
70 fMatU(nullptr),
71 fMatBD(nullptr)
72{
73}
74
75//______________________________________________________
76MinResSolve::MinResSolve(const MatrixSq* mat, const TVectorD* rhs)
77 : fSize(mat->GetSize()),
78 fPrecon(0),
79 fMatrix((MatrixSq*)mat),
80 fRHS((double*)rhs->GetMatrixArray()),
81 fPVecY(nullptr),
82 fPVecR1(nullptr),
83 fPVecR2(nullptr),
84 fPVecV(nullptr),
85 fPVecW(nullptr),
86 fPVecW1(nullptr),
87 fPVecW2(nullptr),
88 fPvv(nullptr),
89 fPvz(nullptr),
90 fPhh(nullptr),
91 fDiagLU(nullptr),
92 fMatL(nullptr),
93 fMatU(nullptr),
94 fMatBD(nullptr)
95{
96}
97
98//______________________________________________________
99MinResSolve::MinResSolve(const MatrixSq* mat, const double* rhs)
100 : fSize(mat->GetSize()),
101 fPrecon(0),
102 fMatrix((MatrixSq*)mat),
103 fRHS((double*)rhs),
104 fPVecY(nullptr),
105 fPVecR1(nullptr),
106 fPVecR2(nullptr),
107 fPVecV(nullptr),
108 fPVecW(nullptr),
109 fPVecW1(nullptr),
110 fPVecW2(nullptr),
111 fPvv(nullptr),
112 fPvz(nullptr),
113 fPhh(nullptr),
114 fDiagLU(nullptr),
115 fMatL(nullptr),
116 fMatU(nullptr),
117 fMatBD(nullptr)
118{
119}
120
121//______________________________________________________
126
127//______________________________________________________
129{
130 if (this != &src) {
131 fSize = src.fSize;
132 fPrecon = src.fPrecon;
133 fMatrix = src.fMatrix;
134 fRHS = src.fRHS;
135 }
136 return *this;
137}
138
139//_______________________________________________________________
141{
142 fPrecon = prec;
143
144 if (fPrecon >= kPreconBD && fPrecon < kPreconILU0) { // band diagonal decomposition
145 return BuildPreconBD(fPrecon - kPreconBD); // with halfbandwidth + diagonal = fPrecon
146 }
147
149 if (fMatrix->InheritsFrom("MatrixSparse")) {
151 } else {
153 }
154 }
155
156 return -1;
157}
158
159//________________________________ FGMRES METHODS ________________________________
160Bool_t MinResSolve::SolveFGMRES(TVectorD& VecSol, Int_t precon, int itnlim, double rtol, int nkrylov)
161{
162 // solve by fgmres
163 return SolveFGMRES(VecSol.GetMatrixArray(), precon, itnlim, rtol, nkrylov);
164}
165
166//________________________________________________________________________________
167Bool_t MinResSolve::SolveFGMRES(double* VecSol, Int_t precon, int itnlim, double rtol, int nkrylov)
168{
169 // Adapted from Y.Saad fgmrs.c of ITSOL_1 package by Y.Saad: http://www-users.cs.umn.edu/~saad/software/
170 /*----------------------------------------------------------------------
171 | *** Preconditioned FGMRES ***
172 +-----------------------------------------------------------------------
173 | This is a simple version of the ARMS preconditioned FGMRES algorithm.
174 +-----------------------------------------------------------------------
175 | Y. S. Dec. 2000. -- Apr. 2008
176 +-----------------------------------------------------------------------
177 | VecSol = real vector of length n containing an initial guess to the
178 | precon = precondtioner id (0 = no precon)
179 | itnlim = max n of iterations
180 | rtol = tolerance for stopping iteration
181 | nkrylov = N of Krylov vectors to store
182 +---------------------------------------------------------------------*/
183 int l;
184 double status = kTRUE;
185 double t, beta, eps1 = 0;
186 const double epsmac = 2.22E-16;
187
188 LOG(info) << "Solution by FGMRes: Preconditioner #" << precon
189 << " Max.iter.: " << itnlim
190 << std::scientific << std::setprecision(3) << " Tol.: " << rtol
191 << "NKrylov: " << nkrylov;
192
193 int its = 0;
194 if (nkrylov < 10) {
195 LOG(info) << "Changing N Krylov vectors from " << nkrylov << " 10";
196 nkrylov = 10;
197 }
198
199 if (precon > 0) {
200 if (precon >= kPreconsTot) {
201 LOG(warning) << "Unknown preconditioner identifier " << precon << ", ignore";
202 } else {
203 if (BuildPrecon(precon) < 0) {
204 ClearAux();
205 LOG(error) << "FGMRES failed to build the preconditioner";
206 return kFALSE;
207 }
208 }
209 }
210
211 if (!InitAuxFGMRES(nkrylov)) {
212 return kFALSE;
213 }
214
215 for (l = fSize; l--;) {
216 VecSol[l] = 0;
217 }
218
219 //-------------------- outer loop starts here
220 TStopwatch timer;
221 timer.Start();
222 while (1) {
223
224 //-------------------- compute initial residual vector
225 fMatrix->MultiplyByVec(VecSol, fPvv[0]);
226 for (l = fSize; l--;) {
227 fPvv[0][l] = fRHS[l] - fPvv[0][l]; // fPvv[0]= initial residual
228 }
229 beta = 0;
230 for (l = fSize; l--;) {
231 beta += fPvv[0][l] * fPvv[0][l];
232 }
233 beta = TMath::Sqrt(beta);
234
235 if (beta < epsmac) {
236 break; // success?
237 }
238 t = 1.0 / beta;
239 //-------------------- normalize: fPvv[0] = fPvv[0] / beta
240 for (l = fSize; l--;) {
241 fPvv[0][l] *= t;
242 }
243 if (its == 0) {
244 eps1 = rtol * beta;
245 }
246
247 // ** initialize 1-st term of rhs of hessenberg system
248 fPVecV[0] = beta;
249 int i = -1;
250 do {
251 i++;
252 its++;
253 int i1 = i + 1;
254
255 // (Right) Preconditioning Operation z_{j} = M^{-1} v_{j}
256
257 if (precon > 0) {
258 ApplyPrecon(fPvv[i], fPvz[i]);
259 } else {
260 for (l = fSize; l--;) {
261 fPvz[i][l] = fPvv[i][l];
262 }
263 }
264
265 //-------------------- matvec operation w = A z_{j} = A M^{-1} v_{j}
267
268 // modified gram - schmidt...
269 // h_{i,j} = (w,v_{i})
270 // w = w - h_{i,j} v_{i}
271
272 for (int j = 0; j <= i; j++) {
273 for (t = 0, l = fSize; l--;) {
274 t += fPvv[j][l] * fPvv[i1][l];
275 }
276 fPhh[i][j] = t;
277 for (l = fSize; l--;) {
278 fPvv[i1][l] -= t * fPvv[j][l];
279 }
280 }
281 // -------------------- h_{j+1,j} = ||w||_{2}
282 for (t = 0, l = fSize; l--;) {
283 t += fPvv[i1][l] * fPvv[i1][l];
284 }
285 t = TMath::Sqrt(t);
286 fPhh[i][i1] = t;
287 if (t > 0) {
288 for (t = 1. / t, l = 0; l < fSize; l++) {
289 fPvv[i1][l] *= t; // v_{j+1} = w / h_{j+1,j}
290 }
291 }
292 // done with modified gram schimdt and arnoldi step
293 // now update factorization of fPhh
294 //
295 // perform previous transformations on i-th column of h
296
297 for (l = 1; l <= i; l++) {
298 int l1 = l - 1;
299 t = fPhh[i][l1];
300 fPhh[i][l1] = fPVecR1[l1] * t + fPVecR2[l1] * fPhh[i][l];
301 fPhh[i][l] = -fPVecR2[l1] * t + fPVecR1[l1] * fPhh[i][l];
302 }
303 double gam = TMath::Sqrt(fPhh[i][i] * fPhh[i][i] + fPhh[i][i1] * fPhh[i][i1]);
304
305 // if gamma is zero then any small value will do...
306 // will affect only residual estimate
307 if (gam < epsmac) {
308 gam = epsmac;
309 }
310 // get next plane rotation
311 fPVecR1[i] = fPhh[i][i] / gam;
312 fPVecR2[i] = fPhh[i][i1] / gam;
313 fPVecV[i1] = -fPVecR2[i] * fPVecV[i];
314 fPVecV[i] *= fPVecR1[i];
315
316 // determine residual norm and test for convergence
317 fPhh[i][i] = fPVecR1[i] * fPhh[i][i] + fPVecR2[i] * fPhh[i][i1];
318 beta = TMath::Abs(fPVecV[i1]);
319 //
320 } while ((i < nkrylov - 1) && (beta > eps1) && (its < itnlim));
321 //
322 // now compute solution. 1st, solve upper triangular system
323 fPVecV[i] = fPVecV[i] / fPhh[i][i];
324 for (int j = 1; j <= i; j++) {
325 int k = i - j;
326 for (t = fPVecV[k], l = k + 1; l <= i; l++) {
327 t -= fPhh[l][k] * fPVecV[l];
328 }
329 fPVecV[k] = t / fPhh[k][k];
330 }
331 // -------------------- linear combination of v[i]'s to get sol.
332 for (int j = 0; j <= i; j++) {
333 for (t = fPVecV[j], l = 0; l < fSize; l++) {
334 VecSol[l] += t * fPvz[j][l];
335 }
336 }
337 // -------------------- restart outer loop if needed
338
339 if (beta <= eps1) {
340 timer.Stop();
341 LOG(info) << "FGMRES converged in " << its
342 << " iterations, CPU time: "
343 << std::setprecision(1) << timer.CpuTime() << " sec";
344 break; // success
345 }
346
347 if (its >= itnlim) {
348 timer.Stop();
349 LOG(error) << itnlim << " iterations limit exceeded, CPU time: "
350 << std::setprecision(1) << timer.CpuTime() << " sec";
351 status = kFALSE;
352 break;
353 }
354 }
355
356 ClearAux();
357 return status;
358}
359
360//________________________________ MINRES METHODS ________________________________
361Bool_t MinResSolve::SolveMinRes(TVectorD& VecSol, Int_t precon, int itnlim, double rtol)
362{
363 // solve by minres
364 return SolveMinRes(VecSol.GetMatrixArray(), precon, itnlim, rtol);
365}
366
367//________________________________________________________________________________
368Bool_t MinResSolve::SolveMinRes(double* VecSol, Int_t precon, int itnlim, double rtol)
369{
370 /*
371 Adapted from author's Fortran code:
372 Michael A. Saunders na.msaunders@na-net.ornl.gov
373
374 MINRES is an implementation of the algorithm described in the following reference:
375 C. C. Paige and M. A. Saunders (1975),
376 Solution of sparse indefinite systems of linear equations,
377 SIAM J. Numer. Anal. 12(4), pp. 617-629.
378
379 */
380 if (!fMatrix->IsSymmetric()) {
381 LOG(error) << "MinRes cannot solve asymmetric matrices, use FGMRes instead";
382 return kFALSE;
383 }
384
385 ClearAux();
386 const double eps = 2.22E-16;
387 double beta1;
388
389 if (precon > 0) {
390 if (precon >= kPreconsTot) {
391 LOG(warning) << "Unknown preconditioner identifier "
392 << precon << ", ignore";
393 } else {
394 if (BuildPrecon(precon) < 0) {
395 ClearAux();
396 LOG(error) << "MinRes failed to build the preconditioner";
397 return kFALSE;
398 }
399 }
400 }
401 LOG(info) << "Solution by MinRes: Preconditioner #" << precon
402 << " Max.iter.: " << itnlim << " Tol.: "
403 << std::scientific << std::setprecision(3) << rtol;
404
405 // ------------------------ initialization ---------------------->>>>
406 memset(VecSol, 0, fSize * sizeof(double));
407 int status = 0, itn = 0;
408 double normA = 0;
409 double condA = 0;
410 double ynorm = 0;
411 double rnorm = 0;
412 double gam, gmax = 1, gmin = 1, gbar, oldeps, epsa, epsx, epsr, diag, delta, phi, denom, z;
413
414 if (!InitAuxMinRes()) {
415 return kFALSE;
416 }
417
418 memset(VecSol, 0, fSize * sizeof(double));
419
420 // ------------ init aux -------------------------<<<<
421 // Set up y and v for the first Lanczos vector v1.
422 // y = beta1 P' v1, where P = C**(-1). v is really P' v1.
423
424 for (int i = fSize; i--;) {
425 fPVecY[i] = fPVecR1[i] = fRHS[i];
426 }
427
428 if (precon > 0) {
430 }
431 beta1 = 0;
432 for (int i = fSize; i--;) {
433 beta1 += fRHS[i] * fPVecY[i];
434 }
435
436 if (beta1 < 0) {
437 LOG(error) << "Preconditioner is indefinite (init) ("
438 << std::scientific << std::setprecision(3) << beta1 << ").";
439 ClearAux();
440 status = 7;
441 return kFALSE;
442 }
443
444 if (beta1 < eps) {
445 LOG(warning) << "RHS is zero or is the nullspace of the Preconditioner: Solution is {0}";
446 ClearAux();
447 return kTRUE;
448 }
449
450 beta1 = TMath::Sqrt(beta1); // Normalize y to get v1 later.
451
452 // See if Msolve is symmetric. //RS: Skept
453 // See if Aprod is symmetric. //RS: Skept
454
455 double oldb = 0;
456 double beta = beta1;
457 double dbar = 0;
458 double epsln = 0;
459 double qrnorm = beta1;
460 double phibar = beta1;
461 double rhs1 = beta1;
462 double rhs2 = 0;
463 double tnorm2 = 0;
464 double ynorm2 = 0;
465 double cs = -1;
466 double sn = 0;
467 for (int i = fSize; i--;) {
468 fPVecR2[i] = fPVecR1[i];
469 }
470
471 TStopwatch timer;
472 timer.Start();
473 while (status == 0) { //----------------- Main iteration loop ---------------------->>>>
474
475 itn++;
476 /*-----------------------------------------------------------------
477 Obtain quantities for the next Lanczos vector vk+1, k = 1, 2,...
478 The general iteration is similar to the case k = 1 with v0 = 0:
479 p1 = Operator * v1 - beta1 * v0,
480 alpha1 = v1'p1,
481 q2 = p2 - alpha1 * v1,
482 beta2^2 = q2'q2,
483 v2 = (1/beta2) q2.
484 Again, y = betak P vk, where P = C**(-1).
485 .... more description needed.
486 -----------------------------------------------------------------*/
487
488 double s = 1. / beta; // Normalize previous vector (in y).
489 for (int i = fSize; i--;) {
490 fPVecV[i] = s * fPVecY[i]; // v = vk if P = I
491 }
492 fMatrix->MultiplyByVec(fPVecV, fPVecY); // APROD (VecV, VecY);
493
494 if (itn >= 2) {
495 double btrat = beta / oldb;
496 for (int i = fSize; i--;) {
497 fPVecY[i] -= btrat * fPVecR1[i];
498 }
499 }
500 double alfa = 0;
501 for (int i = fSize; i--;) {
502 alfa += fPVecV[i] * fPVecY[i]; // alphak
503 }
504 double alf2bt = alfa / beta;
505 for (int i = fSize; i--;) {
506 fPVecY[i] -= alf2bt * fPVecR2[i];
507 fPVecR1[i] = fPVecR2[i];
508 fPVecR2[i] = fPVecY[i];
509 }
510
511 if (precon > 0) {
513 }
514
515 oldb = beta; // oldb = betak
516 beta = 0;
517 for (int i = fSize; i--;) {
518 beta += fPVecR2[i] * fPVecY[i]; // beta = betak+1^2
519 }
520 if (beta < 0) {
521 LOG(error) << "Preconditioner is indefinite ("
522 << std::scientific << std::setprecision(3) << beta << ").";
523 status = 7;
524 break;
525 }
526
527 beta = TMath::Sqrt(beta); // beta = betak+1
528 tnorm2 += alfa * alfa + oldb * oldb + beta * beta;
529
530 if (itn == 1) { // Initialize a few things.
531 if (beta / beta1 <= 10.0 * eps) {
532 status = 0; //-1 //????? beta2 = 0 or ~ 0, terminate later.
533 LOG(info) << "RHS is eigenvector";
534 }
535 // !tnorm2 = alfa**2
536 gmax = TMath::Abs(alfa); // alpha1
537 gmin = gmax; // alpha1
538 }
539
540 /*
541 Apply previous rotation Qk-1 to get
542 [deltak epslnk+1] = [cs sn][dbark 0 ]
543 [gbar k dbar k+1] [sn -cs][alfak betak+1].
544 */
545
546 oldeps = epsln;
547 delta = cs * dbar + sn * alfa; // delta1 = 0 deltak
548 gbar = sn * dbar - cs * alfa; // gbar 1 = alfa1 gbar k
549 epsln = sn * beta; // epsln2 = 0 epslnk+1
550 dbar = -cs * beta; // dbar 2 = beta2 dbar k+1
551
552 // Compute the next plane rotation Qk
553
554 gam = TMath::Sqrt(gbar * gbar + beta * beta); // gammak
555 cs = gbar / gam; // ck
556 sn = beta / gam; // sk
557 phi = cs * phibar; // phik
558 phibar = sn * phibar; // phibark+1
559
560 // Update x.
561 denom = 1. / gam;
562
563 for (int i = fSize; i--;) {
564 fPVecW1[i] = fPVecW2[i];
565 fPVecW2[i] = fPVecW[i];
566 fPVecW[i] = denom * (fPVecV[i] - oldeps * fPVecW1[i] - delta * fPVecW2[i]);
567 VecSol[i] += phi * fPVecW[i];
568 }
569
570 // Go round again.
571
572 gmax = TMath::Max(gmax, gam);
573 gmin = TMath::Min(gmin, gam);
574 z = rhs1 / gam;
575 ynorm2 += z * z;
576 rhs1 = rhs2 - delta * z;
577 rhs2 = -epsln * z;
578
579 // Estimate various norms and test for convergence.
580 normA = TMath::Sqrt(tnorm2);
581 ynorm = TMath::Sqrt(ynorm2);
582 epsa = normA * eps;
583 epsx = normA * ynorm * eps;
584 epsr = normA * ynorm * rtol;
585 diag = gbar;
586 if (diag == 0) {
587 diag = epsa;
588 }
589 //
590 qrnorm = phibar;
591 rnorm = qrnorm;
592 /*
593 Estimate cond(A).
594 In this version we look at the diagonals of R in the
595 factorization of the lower Hessenberg matrix, Q * H = R,
596 where H is the tridiagonal matrix from Lanczos with one
597 extra row, beta(k+1) e_k^T.
598 */
599 condA = gmax / gmin;
600
601 // See if any of the stopping criteria are satisfied.
602 // In rare cases, istop is already -1 from above (Abar = const*I).
603
604 LOG(debug) << Form("#%5d |qnrm: %+.2e Anrm:%+.2e Cnd:%+.2e Rnrm:%+.2e Ynrm:%+.2e EpsR:%+.2e EpsX:%+.2e Beta1:%+.2e",
605 itn, qrnorm, normA, condA, rnorm, ynorm, epsr, epsx, beta1);
606
607 if (status == 0) {
608 if (itn >= itnlim) {
609 status = 5;
610 LOG(error) << itnlim << " iterations limit exceeded";
611 }
612 if (condA >= 0.1 / eps) {
613 status = 4;
614 LOG(error) << "Matrix condition number "
615 << std::scientific << std::setprecision(3) << condA
616 << " exceeds limit "
617 << std::scientific << std::setprecision(3) << 0.1 / eps;
618 }
619 if (epsx >= beta1) {
620 status = 3;
621 LOG(warning) << "Approximate convergence";
622 }
623 if (qrnorm <= epsx) {
624 status = 2;
625 LOG(info) << "Converged within machine precision";
626 }
627 if (qrnorm <= epsr) {
628 status = 1;
629 LOG(info) << "Converged";
630 }
631 }
632
633 } //----------------- Main iteration loop ----------------------<<<
634
635 ClearAux();
636
637 timer.Stop();
638 LOG(info) << Form(
639 "Exit from MinRes: CPU time: %.2f sec\n"
640 "Status : %2d\n"
641 "Iterations: %4d\n"
642 "Norm : %+e\n"
643 "Condition : %+e\n"
644 "Res.Norm : %+e\n"
645 "Sol.Norm : %+e",
646 timer.CpuTime(), status, itn, normA, condA, rnorm, ynorm);
647
648 return status >= 0 && status <= 3;
649}
650
651//______________________________________________________________
652void MinResSolve::ApplyPrecon(const TVectorD& vecRHS, TVectorD& vecOut) const
653{
654 // apply precond.
655 ApplyPrecon(vecRHS.GetMatrixArray(), vecOut.GetMatrixArray());
656}
657
658//______________________________________________________________
659void MinResSolve::ApplyPrecon(const double* vecRHS, double* vecOut) const
660{
661 if (fPrecon >= kPreconBD && fPrecon < kPreconILU0) { // band diagonal decomposition
662 fMatBD->Solve(vecRHS, vecOut);
663 // return;
664 }
665
666 else if (fPrecon >= kPreconILU0 && fPrecon <= kPreconILU10) {
667
668 for (int i = 0; i < fSize; i++) { // Block L solve
669 vecOut[i] = vecRHS[i];
670 VectorSparse& rowLi = *fMatL->GetRow(i);
671 int n = rowLi.GetNElems();
672 for (int j = 0; j < n; j++) {
673 vecOut[i] -= vecOut[rowLi.GetIndex(j)] * rowLi.GetElem(j);
674 }
675 }
676
677 for (int i = fSize; i--;) { // Block -- U solve
678 VectorSparse& rowUi = *fMatU->GetRow(i);
679 int n = rowUi.GetNElems();
680 for (int j = 0; j < n; j++) {
681 vecOut[i] -= vecOut[rowUi.GetIndex(j)] * rowUi.GetElem(j);
682 }
683 vecOut[i] *= fDiagLU[i];
684 }
685 }
686}
687
688//___________________________________________________________
690{
691 fPVecY = new double[fSize];
692 fPVecR1 = new double[fSize];
693 fPVecR2 = new double[fSize];
694 fPVecV = new double[fSize];
695 fPVecW = new double[fSize];
696 fPVecW1 = new double[fSize];
697 fPVecW2 = new double[fSize];
698
699 for (int i = fSize; i--;) {
700 fPVecY[i] = fPVecR1[i] = fPVecR2[i] = fPVecV[i] = fPVecW[i] = fPVecW1[i] = fPVecW2[i] = 0.0;
701 }
702 return kTRUE;
703}
704
705//___________________________________________________________
706Bool_t MinResSolve::InitAuxFGMRES(int nkrylov)
707{
708 fPvv = new double*[nkrylov + 1];
709 fPvz = new double*[nkrylov];
710 for (int i = 0; i <= nkrylov; i++) {
711 fPvv[i] = new double[fSize];
712 }
713 fPhh = new double*[nkrylov];
714 for (int i = 0; i < nkrylov; i++) {
715 fPhh[i] = new double[i + 2];
716 fPvz[i] = new double[fSize];
717 }
718
719 fPVecR1 = new double[nkrylov];
720 fPVecR2 = new double[nkrylov];
721 fPVecV = new double[nkrylov + 1];
722
723 return kTRUE;
724}
725
726//___________________________________________________________
728{
729 if (fPVecY) {
730 delete[] fPVecY;
731 }
732 fPVecY = nullptr;
733 if (fPVecR1) {
734 delete[] fPVecR1;
735 }
736 fPVecR1 = nullptr;
737 if (fPVecR2) {
738 delete[] fPVecR2;
739 }
740 fPVecR2 = nullptr;
741 if (fPVecV) {
742 delete[] fPVecV;
743 }
744 fPVecV = nullptr;
745 if (fPVecW) {
746 delete[] fPVecW;
747 }
748 fPVecW = nullptr;
749 if (fPVecW1) {
750 delete[] fPVecW1;
751 }
752 fPVecW1 = nullptr;
753 if (fPVecW2) {
754 delete[] fPVecW2;
755 }
756 fPVecW2 = nullptr;
757 if (fDiagLU) {
758 delete[] fDiagLU;
759 }
760 fDiagLU = nullptr;
761 if (fMatL) {
762 delete fMatL;
763 }
764 fMatL = nullptr;
765 if (fMatU) {
766 delete fMatU;
767 }
768 fMatU = nullptr;
769 if (fMatBD) {
770 delete fMatBD;
771 }
772 fMatBD = nullptr;
773}
774
775//___________________________________________________________
776Int_t MinResSolve::BuildPreconBD(Int_t hwidth)
777{
778 LOG(info) << "Building Band-Diagonal preconditioner of half-width = "
779 << hwidth;
780 fMatBD = new SymBDMatrix(fMatrix->GetSize(), hwidth);
781
782 // fill the band-diagonal part of the matrix
783 if (fMatrix->InheritsFrom("MatrixSparse")) {
784 for (int ir = fMatrix->GetSize(); ir--;) {
785 int jmin = TMath::Max(0, ir - hwidth);
786 VectorSparse& irow = *((MatrixSparse*)fMatrix)->GetRow(ir);
787 for (int j = irow.GetNElems(); j--;) {
788 int jind = irow.GetIndex(j);
789 if (jind < jmin) {
790 break;
791 }
792 (*fMatBD)(ir, jind) = irow.GetElem(j);
793 }
794 }
795 } else {
796 for (int ir = fMatrix->GetSize(); ir--;) {
797 int jmin = TMath::Max(0, ir - hwidth);
798 for (int jr = jmin; jr <= ir; jr++) {
799 (*fMatBD)(ir, jr) = fMatrix->Query(ir, jr);
800 }
801 }
802 }
803
805
806 return 0;
807}
808
809//___________________________________________________________
811{
812 /*----------------------------------------------------------------------------
813 * ILUK preconditioner
814 * incomplete LU factorization with level of fill dropping
815 * Adapted from iluk.c of ITSOL_1 package by Y.Saad: http://www-users.cs.umn.edu/~saad/software/
816 *----------------------------------------------------------------------------*/
817
818 LOG(info) << "Building ILU" << lofM << " preconditioner";
819
820 TStopwatch sw;
821 sw.Start();
822 fMatL = new MatrixSparse(fSize);
823 fMatU = new MatrixSparse(fSize);
824 fMatL->SetSymmetric(kFALSE);
825 fMatU->SetSymmetric(kFALSE);
826 fDiagLU = new Double_t[fSize];
828
829 // symbolic factorization to calculate level of fill index arrays
830 if (PreconILUKsymb(lofM) < 0) {
831 ClearAux();
832 return -1;
833 }
834
835 Int_t* jw = new Int_t[fSize];
836 for (int j = fSize; j--;) {
837 jw[j] = -1; // set indicator array jw to -1
838 }
839 for (int i = 0; i < fSize; i++) { // beginning of main loop
840 if ((i % int(0.1 * fSize)) == 0) {
841 LOG(info) << "BuildPrecon: row " << i << " of " << fSize;
842 sw.Stop();
843 sw.Print();
844 sw.Start(kFALSE);
845 }
846 /* setup array jw[], and initial i-th row */
847 VectorSparse& rowLi = *fMatL->GetRow(i);
848 VectorSparse& rowUi = *fMatU->GetRow(i);
849 VectorSparse& rowM = *matrix->GetRow(i);
850 //
851 for (int j = rowLi.GetNElems(); j--;) { // initialize L part
852 int col = rowLi.GetIndex(j);
853 jw[col] = j;
854 rowLi.GetElem(j) = 0.; // do we need this ?
855 }
856 jw[i] = i;
857 fDiagLU[i] = 0; // initialize diagonal
858 //
859 for (int j = rowUi.GetNElems(); j--;) { // initialize U part
860 int col = rowUi.GetIndex(j);
861 jw[col] = j;
862 rowUi.GetElem(j) = 0;
863 }
864 // copy row from csmat into L,U D
865 for (int j = rowM.GetNElems(); j--;) { // L and D part
866 if (MatrixSq::IsZero(rowM.GetElem(j))) {
867 continue;
868 }
869 int col = rowM.GetIndex(j); // (the original matrix stores only lower triangle)
870 if (col < i) {
871 rowLi.GetElem(jw[col]) = rowM.GetElem(j);
872 } else {
873 if (col == i) {
874 fDiagLU[i] = rowM.GetElem(j);
875 } else {
876 rowUi.GetElem(jw[col]) = rowM.GetElem(j);
877 }
878 }
879 }
880 if (matrix->IsSymmetric()) {
881 for (int col = i + 1; col < fSize; col++) { // part of the row I on the right of diagonal is stored as
882 double vl = matrix->Query(col, i); // the lower part of the column I
883 if (MatrixSq::IsZero(vl)) {
884 continue;
885 }
886 rowUi.GetElem(jw[col]) = vl;
887 }
888 }
889
890 // eliminate previous rows
891 for (int j = 0; j < rowLi.GetNElems(); j++) {
892 int jrow = rowLi.GetIndex(j);
893 // get the multiplier for row to be eliminated (jrow)
894 rowLi.GetElem(j) *= fDiagLU[jrow];
895 //
896 // combine current row and row jrow
897 VectorSparse& rowUj = *fMatU->GetRow(jrow);
898 for (int k = 0; k < rowUj.GetNElems(); k++) {
899 int col = rowUj.GetIndex(k);
900 int jpos = jw[col];
901 if (jpos == -1) {
902 continue;
903 }
904 if (col < i) {
905 rowLi.GetElem(jpos) -= rowLi.GetElem(j) * rowUj.GetElem(k);
906 } else {
907 if (col == i) {
908 fDiagLU[i] -= rowLi.GetElem(j) * rowUj.GetElem(k);
909 } else {
910 rowUi.GetElem(jpos) -= rowLi.GetElem(j) * rowUj.GetElem(k);
911 }
912 }
913 }
914 }
915 // reset double-pointer to -1 ( U-part)
916 for (int j = rowLi.GetNElems(); j--;) {
917 jw[rowLi.GetIndex(j)] = -1;
918 }
919 jw[i] = -1;
920 for (int j = rowUi.GetNElems(); j--;) {
921 jw[rowUi.GetIndex(j)] = -1;
922 }
923
924 if (MatrixSq::IsZero(fDiagLU[i])) {
925 LOG(fatal) << "Fatal error in ILIk: Zero diagonal found...";
926 delete[] jw;
927 return -1;
928 }
929 fDiagLU[i] = 1.0 / fDiagLU[i];
930 }
931
932 delete[] jw;
933
934 sw.Stop();
935 LOG(info) << "ILU" << lofM << "preconditioner OK, CPU time: "
936 << std::setprecision(1) << sw.CpuTime() << " sec";
937 LOG(info) << "Densities: M " << matrix->GetDensity()
938 << " L " << fMatL->GetDensity()
939 << " U " << fMatU->GetDensity();
940
941 return 0;
942}
943
944//___________________________________________________________
946{
947 /*----------------------------------------------------------------------------
948 * ILUK preconditioner
949 * incomplete LU factorization with level of fill dropping
950 * Adapted from iluk.c of ITSOL_1 package by Y.Saad: http://www-users.cs.umn.edu/~saad/software/
951 *----------------------------------------------------------------------------*/
952
953 TStopwatch sw;
954 sw.Start();
955 LOG(info) << "Building ILU" << lofM
956 << " preconditioner for dense matrix";
957
958 fMatL = new MatrixSparse(fSize);
959 fMatU = new MatrixSparse(fSize);
960 fMatL->SetSymmetric(kFALSE);
961 fMatU->SetSymmetric(kFALSE);
962 fDiagLU = new Double_t[fSize];
963
964 // symbolic factorization to calculate level of fill index arrays
965 if (PreconILUKsymbDense(lofM) < 0) {
966 ClearAux();
967 return -1;
968 }
969
970 Int_t* jw = new Int_t[fSize];
971 for (int j = fSize; j--;) {
972 jw[j] = -1; // set indicator array jw to -1
973 }
974 for (int i = 0; i < fSize; i++) { // beginning of main loop
975 /* setup array jw[], and initial i-th row */
976 VectorSparse& rowLi = *fMatL->GetRow(i);
977 VectorSparse& rowUi = *fMatU->GetRow(i);
978
979 for (int j = rowLi.GetNElems(); j--;) { // initialize L part
980 int col = rowLi.GetIndex(j);
981 jw[col] = j;
982 rowLi.GetElem(j) = 0.; // do we need this ?
983 }
984 jw[i] = i;
985 fDiagLU[i] = 0; // initialize diagonal
986
987 for (int j = rowUi.GetNElems(); j--;) { // initialize U part
988 int col = rowUi.GetIndex(j);
989 jw[col] = j;
990 rowUi.GetElem(j) = 0;
991 }
992 // copy row from csmat into L,U D
993 for (int j = fSize; j--;) { // L and D part
994 double vl = fMatrix->Query(i, j);
995 if (MatrixSq::IsZero(vl)) {
996 continue;
997 }
998 if (j < i) {
999 rowLi.GetElem(jw[j]) = vl;
1000 } else {
1001 if (j == i) {
1002 fDiagLU[i] = vl;
1003 } else {
1004 rowUi.GetElem(jw[j]) = vl;
1005 }
1006 }
1007 }
1008 // eliminate previous rows
1009 for (int j = 0; j < rowLi.GetNElems(); j++) {
1010 int jrow = rowLi.GetIndex(j);
1011 // get the multiplier for row to be eliminated (jrow)
1012 rowLi.GetElem(j) *= fDiagLU[jrow];
1013
1014 // combine current row and row jrow
1015 VectorSparse& rowUj = *fMatU->GetRow(jrow);
1016 for (int k = 0; k < rowUj.GetNElems(); k++) {
1017 int col = rowUj.GetIndex(k);
1018 int jpos = jw[col];
1019 if (jpos == -1) {
1020 continue;
1021 }
1022 if (col < i) {
1023 rowLi.GetElem(jpos) -= rowLi.GetElem(j) * rowUj.GetElem(k);
1024 } else {
1025 if (col == i) {
1026 fDiagLU[i] -= rowLi.GetElem(j) * rowUj.GetElem(k);
1027 } else {
1028 rowUi.GetElem(jpos) -= rowLi.GetElem(j) * rowUj.GetElem(k);
1029 }
1030 }
1031 }
1032 }
1033 // reset double-pointer to -1 ( U-part)
1034 for (int j = rowLi.GetNElems(); j--;) {
1035 jw[rowLi.GetIndex(j)] = -1;
1036 }
1037 jw[i] = -1;
1038 for (int j = rowUi.GetNElems(); j--;) {
1039 jw[rowUi.GetIndex(j)] = -1;
1040 }
1041
1042 if (MatrixSq::IsZero(fDiagLU[i])) {
1043 LOG(fatal) << "Fatal error in ILIk: Zero diagonal found...";
1044 delete[] jw;
1045 return -1;
1046 }
1047 fDiagLU[i] = 1.0 / fDiagLU[i];
1048 }
1049
1050 delete[] jw;
1051
1052 sw.Stop();
1053 LOG(info) << "ILU" << lofM << " dense preconditioner OK, CPU time: "
1054 << std::setprecision(1) << sw.CpuTime()
1055 << " sec";
1056 /*
1057 LOG(info) << "Densities: M " << matrix->GetDensity()
1058 << " L " << fMatL->GetDensity()
1059 << " U " << fMatU->GetDensity();
1060 */
1061 return 0;
1062}
1063
1064//___________________________________________________________
1066{
1067 /*----------------------------------------------------------------------------
1068 * ILUK preconditioner
1069 * incomplete LU factorization with level of fill dropping
1070 * Adapted from iluk.c: lofC of ITSOL_1 package by Y.Saad: http://www-users.cs.umn.edu/~saad/software/
1071 *----------------------------------------------------------------------------*/
1072
1073 TStopwatch sw;
1074 LOG(info) << "PreconILUKsymb >>";
1075 MatrixSparse* matrix = (MatrixSparse*)fMatrix;
1076 sw.Start();
1077
1078 UChar_t **ulvl = nullptr, *levls = nullptr;
1079 UShort_t* jbuf = nullptr;
1080 Int_t* iw = nullptr;
1081 ulvl = new UChar_t*[fSize]; // stores lev-fils for U part of ILU factorization
1082 levls = new UChar_t[fSize];
1083 jbuf = new UShort_t[fSize];
1084 iw = new Int_t[fSize];
1085
1086 for (int j = fSize; j--;) {
1087 iw[j] = -1; // initialize iw
1088 }
1089 for (int i = 0; i < fSize; i++) {
1090 int incl = 0;
1091 int incu = i;
1092 VectorSparse& row = *matrix->GetRow(i);
1093
1094 // assign lof = 0 for matrix elements
1095 for (int j = 0; j < row.GetNElems(); j++) {
1096 int col = row.GetIndex(j);
1097 if (MatrixSq::IsZero(row.GetElem(j))) {
1098 continue; // !!!! matrix is sparse but sometimes 0 appears
1099 }
1100 if (col < i) { // L-part
1101 jbuf[incl] = col;
1102 levls[incl] = 0;
1103 iw[col] = incl++;
1104 } else if (col > i) { // This works only for general matrix
1105 jbuf[incu] = col;
1106 levls[incu] = 0;
1107 iw[col] = incu++;
1108 }
1109 }
1110 if (matrix->IsSymmetric()) {
1111 for (int col = i + 1; col < fSize; col++) { // U-part of symmetric matrix
1112 if (MatrixSq::IsZero(matrix->Query(col, i))) {
1113 continue; // Due to the symmetry == matrix(i,col)
1114 }
1115 jbuf[incu] = col;
1116 levls[incu] = 0;
1117 iw[col] = incu++;
1118 }
1119 }
1120 // symbolic k,i,j Gaussian elimination
1121 int jpiv = -1;
1122 while (++jpiv < incl) {
1123 int k = jbuf[jpiv]; // select leftmost pivot
1124 int kmin = k;
1125 int jmin = jpiv;
1126 for (int j = jpiv + 1; j < incl; j++) {
1127 if (jbuf[j] < kmin) {
1128 kmin = jbuf[j];
1129 jmin = j;
1130 }
1131 }
1132
1133 // ------------------------------------ swap
1134 if (jmin != jpiv) {
1135 jbuf[jpiv] = kmin;
1136 jbuf[jmin] = k;
1137 iw[kmin] = jpiv;
1138 iw[k] = jmin;
1139 int tj = levls[jpiv];
1140 levls[jpiv] = levls[jmin];
1141 levls[jmin] = tj;
1142 k = kmin;
1143 }
1144 // ------------------------------------ symbolic linear combinaiton of rows
1145 VectorSparse& rowU = *fMatU->GetRow(k);
1146 for (int j = 0; j < rowU.GetNElems(); j++) {
1147 int col = rowU.GetIndex(j);
1148 int it = ulvl[k][j] + levls[jpiv] + 1;
1149 if (it > lofM) {
1150 continue;
1151 }
1152 int ip = iw[col];
1153 if (ip == -1) {
1154 if (col < i) {
1155 jbuf[incl] = col;
1156 levls[incl] = it;
1157 iw[col] = incl++;
1158 } else if (col > i) {
1159 jbuf[incu] = col;
1160 levls[incu] = it;
1161 iw[col] = incu++;
1162 }
1163 } else {
1164 levls[ip] = TMath::Min(levls[ip], it);
1165 }
1166 }
1167 } // end - while loop
1168
1169 // reset iw
1170 for (int j = 0; j < incl; j++) {
1171 iw[jbuf[j]] = -1;
1172 }
1173 for (int j = i; j < incu; j++) {
1174 iw[jbuf[j]] = -1;
1175 }
1176
1177 // copy L-part
1178 VectorSparse& rowLi = *fMatL->GetRow(i);
1179 rowLi.ReSize(incl);
1180 if (incl > 0) {
1181 memcpy(rowLi.GetIndices(), jbuf, sizeof(UShort_t) * incl);
1182 }
1183 // copy U-part
1184 int k = incu - i;
1185 VectorSparse& rowUi = *fMatU->GetRow(i);
1186 rowUi.ReSize(k);
1187 if (k > 0) {
1188 memcpy(rowUi.GetIndices(), jbuf + i, sizeof(UShort_t) * k);
1189 ulvl[i] = new UChar_t[k]; // update matrix of levels
1190 memcpy(ulvl[i], levls + i, k * sizeof(UChar_t));
1191 }
1192 }
1193
1194 // free temp space and leave
1195 delete[] levls;
1196 delete[] jbuf;
1197 for (int i = fSize; i--;) {
1198 if (fMatU->GetRow(i)->GetNElems()) {
1199 delete[] ulvl[i];
1200 }
1201 }
1202 delete[] ulvl;
1203 delete[] iw;
1204
1205 fMatL->SortIndices();
1206 fMatU->SortIndices();
1207 sw.Stop();
1208 sw.Print();
1209 LOG(info) << "PreconILUKsymb <<";
1210 return 0;
1211}
1212
1213//___________________________________________________________
1215{
1216 /*----------------------------------------------------------------------------
1217 * ILUK preconditioner
1218 * incomplete LU factorization with level of fill dropping
1219 * Adapted from iluk.c: lofC of ITSOL_1 package by Y.Saad: http://www-users.cs.umn.edu/~saad/software/
1220 *----------------------------------------------------------------------------*/
1221 //
1222 UChar_t **ulvl = nullptr, *levls = nullptr;
1223 UShort_t* jbuf = nullptr;
1224 Int_t* iw = nullptr;
1225 ulvl = new UChar_t*[fSize]; // stores lev-fils for U part of ILU factorization
1226 levls = new UChar_t[fSize];
1227 jbuf = new UShort_t[fSize];
1228 iw = new Int_t[fSize];
1229
1230 for (int j = fSize; j--;) {
1231 iw[j] = -1; // initialize iw
1232 }
1233 for (int i = 0; i < fSize; i++) {
1234 int incl = 0;
1235 int incu = i;
1236
1237 // assign lof = 0 for matrix elements
1238 for (int j = 0; j < fSize; j++) {
1239 if (MatrixSq::IsZero(fMatrix->Query(i, j))) {
1240 continue;
1241 }
1242 if (j < i) { // L-part
1243 jbuf[incl] = j;
1244 levls[incl] = 0;
1245 iw[j] = incl++;
1246 } else if (j > i) { // This works only for general matrix
1247 jbuf[incu] = j;
1248 levls[incu] = 0;
1249 iw[j] = incu++;
1250 }
1251 }
1252
1253 // symbolic k,i,j Gaussian elimination
1254 int jpiv = -1;
1255 while (++jpiv < incl) {
1256 int k = jbuf[jpiv]; // select leftmost pivot
1257 int kmin = k;
1258 int jmin = jpiv;
1259 for (int j = jpiv + 1; j < incl; j++) {
1260 if (jbuf[j] < kmin) {
1261 kmin = jbuf[j];
1262 jmin = j;
1263 }
1264 }
1265
1266 // ------------------------------------ swap
1267 if (jmin != jpiv) {
1268 jbuf[jpiv] = kmin;
1269 jbuf[jmin] = k;
1270 iw[kmin] = jpiv;
1271 iw[k] = jmin;
1272 int tj = levls[jpiv];
1273 levls[jpiv] = levls[jmin];
1274 levls[jmin] = tj;
1275 k = kmin;
1276 }
1277 // ------------------------------------ symbolic linear combinaiton of rows
1278 VectorSparse& rowU = *fMatU->GetRow(k);
1279 for (int j = 0; j < rowU.GetNElems(); j++) {
1280 int col = rowU.GetIndex(j);
1281 int it = ulvl[k][j] + levls[jpiv] + 1;
1282 if (it > lofM) {
1283 continue;
1284 }
1285 int ip = iw[col];
1286 if (ip == -1) {
1287 if (col < i) {
1288 jbuf[incl] = col;
1289 levls[incl] = it;
1290 iw[col] = incl++;
1291 } else if (col > i) {
1292 jbuf[incu] = col;
1293 levls[incu] = it;
1294 iw[col] = incu++;
1295 }
1296 } else {
1297 levls[ip] = TMath::Min(levls[ip], it);
1298 }
1299 }
1300 } // end - while loop
1301
1302 // reset iw
1303 for (int j = 0; j < incl; j++) {
1304 iw[jbuf[j]] = -1;
1305 }
1306 for (int j = i; j < incu; j++) {
1307 iw[jbuf[j]] = -1;
1308 }
1309
1310 // copy L-part
1311 VectorSparse& rowLi = *fMatL->GetRow(i);
1312 rowLi.ReSize(incl);
1313 if (incl > 0) {
1314 memcpy(rowLi.GetIndices(), jbuf, sizeof(UShort_t) * incl);
1315 }
1316 // copy U-part
1317 int k = incu - i;
1318 VectorSparse& rowUi = *fMatU->GetRow(i);
1319 rowUi.ReSize(k);
1320 if (k > 0) {
1321 memcpy(rowUi.GetIndices(), jbuf + i, sizeof(UShort_t) * k);
1322 ulvl[i] = new UChar_t[k]; // update matrix of levels
1323 memcpy(ulvl[i], levls + i, k * sizeof(UChar_t));
1324 }
1325 }
1326
1327 // free temp space and leave
1328 delete[] levls;
1329 delete[] jbuf;
1330 for (int i = fSize; i--;) {
1331 if (fMatU->GetRow(i)->GetNElems()) {
1332 delete[] ulvl[i];
1333 }
1334 }
1335 delete[] ulvl;
1336 delete[] iw;
1337
1338 fMatL->SortIndices();
1339 fMatU->SortIndices();
1340 return 0;
1341}
int32_t i
Sparse matrix class (from AliROOT), used as a global matrix for MillePede2.
Abstract class (from AliROOT) for square matrix used for millepede2 operation.
ClassImp(MinResSolve)
General class (from AliROOT) for solving large system of linear equations.
uint32_t j
Definition RawData.h:0
uint32_t col
Definition RawData.h:4
Symmetric Band Diagonal matrix (from AliROOT) with half band width W (+1 for diagonal)
std::ostringstream debug
void SortIndices(Bool_t valuesToo=kFALSE)
sort columns in increasing order. Used to fix the matrix after ILUk decompostion
Float_t GetDensity() const override
get fraction of non-zero elements
VectorSparse * GetRow(Int_t ir) const
static Bool_t IsZero(Double_t x, Double_t thresh=1e-64)
Definition MatrixSq.h:134
Bool_t IsSymmetric() const override
Definition MatrixSq.h:64
virtual Int_t GetSize() const
Definition MatrixSq.h:39
virtual Double_t Query(Int_t rown, Int_t coln) const
Definition MatrixSq.h:44
virtual void MultiplyByVec(const Double_t *vecIn, Double_t *vecOut) const
fill vecOut by matrix * vecIn (vector should be of the same size as the matrix)
Definition MatrixSq.cxx:46
void SetSymmetric(Bool_t v=kTRUE)
Definition MatrixSq.h:65
for solving large system of linear equations
Definition MinResSolve.h:37
MinResSolve()
default constructor
Int_t BuildPreconBD(Int_t hwidth)
build Band-Diagonal preconditioner
MatrixSq * fMatrix
matrix defining the equations
void ApplyPrecon(const TVectorD &vecRHS, TVectorD &vecOut) const
apply precond.
Int_t BuildPreconILUKDense(Int_t lofM)
ILUK preconditioner.
MinResSolve & operator=(const MinResSolve &rhs)
assignment op.
Bool_t InitAuxFGMRES(int nkrylov)
init auxiliary space for fgmres
Int_t fPrecon
preconditioner type
Int_t PreconILUKsymb(Int_t lofM)
ILUK preconditioner.
Double_t * fPVecY
aux. space
Int_t BuildPreconILUK(Int_t lofM)
ILUK preconditioner.
void ClearAux()
clear aux. space
Int_t BuildPrecon(Int_t val=0)
preconditioner building
~MinResSolve() override
destructor
Double_t * fRHS
right hand side
Int_t fSize
dimension of the input matrix
Int_t PreconILUKsymbDense(Int_t lofM)
ILUK preconditioner.
Bool_t InitAuxMinRes()
init auxiliary space for MinRes
Bool_t SolveMinRes(Double_t *VecSol, Int_t precon=0, int itnlim=2000, double rtol=1e-12)
MINRES method (for symmetric matrices)
Bool_t SolveFGMRES(Double_t *VecSol, Int_t precon=0, int itnlim=2000, double rtol=1e-12, int nkrylov=60)
FGMRES method (for general symmetric matrices)
Symmetric Matrix Class.
Definition SymBDMatrix.h:33
void Solve(Double_t *rhs)
solve matrix equation
void DecomposeLDLT()
decomposition to L Diag L^T
UShort_t * GetIndices() const
Double_t & GetElem(Int_t i) const
UShort_t & GetIndex(Int_t i)
void ReSize(Int_t sz, Bool_t copy=kFALSE)
change the size
GLdouble n
Definition glcorearb.h:1982
GLenum src
Definition glcorearb.h:1767
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
TStopwatch sw
std::vector< int > row