Anasazi Version of the Day
Loading...
Searching...
No Matches
ModifiedARPACKm3.cpp
1// @HEADER
2// *****************************************************************************
3// Anasazi: Block Eigensolvers Package
4//
5// Copyright 2004 NTESS and the Anasazi contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10// This software is a result of the research described in the report
11//
12// "A comparison of algorithms for modal analysis in the absence
13// of a sparse direct method", P. Arbenz, R. Lehoucq, and U. Hetmaniuk,
14// Sandia National Laboratories, Technical report SAND2003-1028J.
15//
16// It is based on the Epetra, AztecOO, and ML packages defined in the Trilinos
17// framework ( http://trilinos.org/ ).
18
19#include "ModifiedARPACKm3.h"
20
21
22ModifiedARPACKm3::ModifiedARPACKm3(const Epetra_Comm &_Comm, const Epetra_Operator *KK,
23 double _tol, int _maxIter, int _verb) :
24 myVerify(_Comm),
25 callBLAS(),
26 callFortran(),
27 modalTool(_Comm),
28 mySort(),
29 MyComm(_Comm),
30 K(KK),
31 M(0),
32 MyWatch(_Comm),
33 tolEigenSolve(_tol),
34 maxIterEigenSolve(_maxIter),
35 normWeight(0),
36 verbose(_verb),
37 historyCount(0),
38 resHistory(0),
39 memRequested(0.0),
40 highMem(0.0),
41 massOp(0),
42 numResidual(0),
43 orthoOp(0),
44 outerIter(0),
45 stifOp(0),
46 timeMassOp(0.0),
47 timeOuterLoop(0.0),
48 timePostProce(0.0),
49 timeResidual(0.0),
50 timeStifOp(0.0)
51 {
52
53}
54
55
56ModifiedARPACKm3::ModifiedARPACKm3(const Epetra_Comm &_Comm, const Epetra_Operator *KK,
57 const Epetra_Operator *MM,
58 double _tol, int _maxIter, int _verb, double *_weight) :
59 myVerify(_Comm),
60 callBLAS(),
61 callFortran(),
62 modalTool(_Comm),
63 mySort(),
64 MyComm(_Comm),
65 K(KK),
66 M(MM),
67 MyWatch(_Comm),
68 tolEigenSolve(_tol),
69 maxIterEigenSolve(_maxIter),
70 normWeight(_weight),
71 verbose(_verb),
72 historyCount(0),
73 resHistory(0),
74 memRequested(0.0),
75 highMem(0.0),
76 massOp(0),
77 numResidual(0),
78 orthoOp(0),
79 outerIter(0),
80 stifOp(0),
81 timeMassOp(0.0),
82 timeOuterLoop(0.0),
83 timePostProce(0.0),
84 timeResidual(0.0),
85 timeStifOp(0.0)
86 {
87
88}
89
90
91ModifiedARPACKm3::~ModifiedARPACKm3() {
92
93 if (resHistory) {
94 delete[] resHistory;
95 resHistory = 0;
96 }
97
98}
99
100
101int ModifiedARPACKm3::solve(int numEigen, Epetra_MultiVector &Q, double *lambda) {
102
103 return ModifiedARPACKm3::reSolve(numEigen, Q, lambda, 0, 0);
104
105}
106
107
108int ModifiedARPACKm3::reSolve(int numEigen, Epetra_MultiVector &Q, double *lambda,
109 int startingEV) {
110
111 return ModifiedARPACKm3::reSolve(numEigen, Q, lambda, startingEV, 0);
112
113}
114
115
116int ModifiedARPACKm3::reSolve(int numEigen, Epetra_MultiVector &Q, double *lambda,
117 int startingEV, const Epetra_MultiVector *orthoVec) {
118
119 // Computes the smallest eigenvalues and the corresponding eigenvectors
120 // of the generalized eigenvalue problem
121 //
122 // K X = M X Lambda
123 //
124 // using ModifiedARPACK (mode 3).
125 //
126 // The convergence test is performed outisde of ARPACK
127 //
128 // || Kx - Mx lambda || < tol*lambda
129 //
130 // The norm ||.|| can be specified by the user through the array normWeight.
131 // By default, the L2 Euclidean norm is used.
132 //
133 // Note that if M is not specified, then K X = X Lambda is solved.
134 // (using the mode for generalized eigenvalue problem).
135 //
136 // Input variables:
137 //
138 // numEigen (integer) = Number of eigenmodes requested
139 //
140 // Q (Epetra_MultiVector) = Initial search space
141 // The number of columns of Q defines the size of search space (=NCV).
142 // The rows of X are distributed across processors.
143 // As a rule of thumb in ARPACK User's guide, NCV >= 2*numEigen.
144 // At exit, the first numEigen locations contain the eigenvectors requested.
145 //
146 // lambda (array of doubles) = Converged eigenvalues
147 // The length of this array is equal to the number of columns in Q.
148 // At exit, the first numEigen locations contain the eigenvalues requested.
149 //
150 // startingEV (integer) = Number of eigenmodes already stored in Q
151 // A linear combination of these vectors is made to define the starting
152 // vector, placed in resid.
153 //
154 // orthoVec (Pointer to Epetra_MultiVector) = Space to be orthogonal to
155 // The computation is performed in the orthogonal of the space spanned
156 // by the columns vectors in orthoVec.
157 //
158 // Return information on status of computation
159 //
160 // info >= 0 >> Number of converged eigenpairs at the end of computation
161 //
162 // // Failure due to input arguments
163 //
164 // info = - 1 >> The stiffness matrix K has not been specified.
165 // info = - 2 >> The maps for the matrix K and the matrix M differ.
166 // info = - 3 >> The maps for the matrix K and the preconditioner P differ.
167 // info = - 4 >> The maps for the vectors and the matrix K differ.
168 // info = - 5 >> Q is too small for the number of eigenvalues requested.
169 // info = - 6 >> Q is too small for the computation parameters.
170 //
171 // info = - 8 >> numEigen must be smaller than the dimension of the matrix.
172 //
173 // info = - 30 >> MEMORY
174 //
175 // See ARPACK documentation for the meaning of INFO
176
177 if (numEigen <= startingEV) {
178 return numEigen;
179 }
180
181 int info = myVerify.inputArguments(numEigen, K, M, 0, Q, minimumSpaceDimension(numEigen));
182 if (info < 0)
183 return info;
184
185 int myPid = MyComm.MyPID();
186
187 int localSize = Q.MyLength();
188 int NCV = Q.NumVectors();
189 int knownEV = 0;
190
191 if (NCV > Q.GlobalLength()) {
192 if (numEigen >= Q.GlobalLength()) {
193 cerr << endl;
194 cerr << " !! The number of requested eigenvalues must be smaller than the dimension";
195 cerr << " of the matrix !!\n";
196 cerr << endl;
197 return -8;
198 }
199 NCV = Q.GlobalLength();
200 }
201
202 // Get the weight for approximating the M-inverse norm
203 Epetra_Vector *vectWeight = 0;
204 if (normWeight) {
205 vectWeight = new Epetra_Vector(View, Q.Map(), normWeight);
206 }
207
208 int localVerbose = verbose*(myPid == 0);
209
210 // Define data for ARPACK
211 //
212 // UH (10/17/03) Note that workl is also used
213 // * to store the eigenvectors of the tridiagonal matrix
214 // * as a workspace for DSTEQR
215 // * as a workspace for recovering the global eigenvectors
216
217 highMem = (highMem > currentSize()) ? highMem : currentSize();
218
219 int ido = 0;
220
221 int lwI = 22;
222 int *wI = new (nothrow) int[lwI];
223 if (wI == 0) {
224 if (vectWeight)
225 delete vectWeight;
226 return -30;
227 }
228 memRequested += sizeof(int)*lwI/(1024.0*1024.0);
229
230 int *iparam = wI;
231 int *ipntr = wI + 11;
232
233 int lworkl = NCV*(NCV+8);
234 int lwD = lworkl + 4*localSize;
235 double *wD = new (nothrow) double[lwD];
236 if (wD == 0) {
237 if (vectWeight)
238 delete vectWeight;
239 delete[] wI;
240 return -30;
241 }
242 memRequested += sizeof(double)*(4*localSize+lworkl)/(1024.0*1024.0);
243
244 double *pointer = wD;
245
246 double *workl = pointer;
247 pointer = pointer + lworkl;
248
249 double *resid = pointer;
250 pointer = pointer + localSize;
251
252 double *workd = pointer;
253
254 double *v = Q.Values();
255
256 highMem = (highMem > currentSize()) ? highMem : currentSize();
257
258 if (startingEV > 0) {
259 // Define the initial starting vector
260 memset(resid, 0, localSize*sizeof(double));
261 for (int jj = 0; jj < startingEV; ++jj)
262 for (int ii = 0; ii < localSize; ++ii)
263 resid[ii] += v[ii + jj*localSize];
264 info = 1;
265 }
266
267 iparam[1-1] = 1;
268 iparam[3-1] = maxIterEigenSolve;
269 iparam[7-1] = 3;
270
271 // The fourth parameter forces to use the convergence test provided by ARPACK.
272 // This requires a customization of ARPACK (provided by R. Lehoucq).
273
274 iparam[4-1] = 1;
275
276 Epetra_Vector v1(View, Q.Map(), workd);
277 Epetra_Vector v2(View, Q.Map(), workd + localSize);
278 Epetra_Vector v3(View, Q.Map(), workd + 2*localSize);
279
280 // Define further storage for the new residual check
281 // Use a block of vectors to compute the residuals more quickly.
282 // Note that workd could be used if memory becomes an issue.
283 int loopZ = (NCV > 10) ? 10 : NCV;
284
285 int lwD2 = localSize + 2*NCV-1 + NCV;
286 lwD2 += (M) ? 3*loopZ*localSize : 2*loopZ*localSize;
287 double *wD2 = new (nothrow) double[lwD2];
288 if (wD2 == 0) {
289 if (vectWeight)
290 delete vectWeight;
291 delete[] wI;
292 delete[] wD;
293 return -30;
294 }
295 memRequested += sizeof(double)*lwD2/(1024.0*1024.0);
296
297 pointer = wD2;
298
299 // vTmp is used when ido = -1
300 double *vTmp = pointer;
301 pointer = pointer + localSize;
302
303 // dd and ee stores the tridiagonal matrix.
304 // Note that DSTEQR destroys the contents of the input arrays.
305 double *dd = pointer;
306 pointer = pointer + NCV;
307
308 double *ee = pointer;
309 pointer = pointer + NCV-1;
310
311 double *vz = pointer;
312 pointer = pointer + loopZ*localSize;
313 Epetra_MultiVector approxEV(View, Q.Map(), vz, localSize, loopZ);
314
315 double *kvz = pointer;
316 pointer = pointer + loopZ*localSize;
317 Epetra_MultiVector KapproxEV(View, Q.Map(), kvz, localSize, loopZ);
318
319 double *mvz = (M) ? pointer : vz;
320 pointer = (M) ? pointer + loopZ*localSize : pointer;
321 Epetra_MultiVector MapproxEV(View, Q.Map(), mvz, localSize, loopZ);
322
323 double *normR = pointer;
324
325 // zz contains the eigenvectors of the tridiagonal matrix.
326 // workt is a workspace for DSTEQR.
327 // Note that zz and workt will use parts of workl.
328 double *zz, *workt;
329
330 highMem = (highMem > currentSize()) ? highMem : currentSize();
331
332 // Define an array to store the residuals history
333 if (localVerbose > 2) {
334 resHistory = new (nothrow) double[maxIterEigenSolve*NCV];
335 if (resHistory == 0) {
336 if (vectWeight)
337 delete vectWeight;
338 delete[] wI;
339 delete[] wD;
340 delete[] wD2;
341 return -30;
342 }
343 historyCount = 0;
344 }
345
346 highMem = (highMem > currentSize()) ? highMem : currentSize();
347
348 if (localVerbose > 0) {
349 cout << endl;
350 cout << " *|* Problem: ";
351 if (M)
352 cout << "K*Q = M*Q D ";
353 else
354 cout << "K*Q = Q D ";
355 cout << endl;
356 cout << " *|* Algorithm = ARPACK (Mode 3, modified such that user checks convergence)" << endl;
357 cout << " *|* Number of requested eigenvalues = " << numEigen << endl;
358 cout.precision(2);
359 cout.setf(ios::scientific, ios::floatfield);
360 cout << " *|* Tolerance for convergence = " << tolEigenSolve << endl;
361 if (startingEV > 0)
362 cout << " *|* User-defined starting vector (Combination of " << startingEV << " vectors)\n";
363 cout << " *|* Norm used for convergence: ";
364 if (normWeight)
365 cout << "weighted L2-norm with user-provided weights" << endl;
366 else
367 cout << "L^2-norm" << endl;
368 if (orthoVec)
369 cout << " *|* Size of orthogonal subspace = " << orthoVec->NumVectors() << endl;
370 cout << "\n -- Start iterations -- \n";
371 }
372
373#ifdef EPETRA_MPI
374 Epetra_MpiComm *MPIComm = dynamic_cast<Epetra_MpiComm *>(const_cast<Epetra_Comm*>(&MyComm));
375#endif
376
377 timeOuterLoop -= MyWatch.WallTime();
378 while (ido != 99) {
379
380 highMem = (highMem > currentSize()) ? highMem : currentSize();
381
382#ifdef EPETRA_MPI
383 if (MPIComm)
384 callFortran.PSAUPD(MPIComm->Comm(), &ido, 'G', localSize, "LM", numEigen, tolEigenSolve,
385 resid, NCV, v, localSize, iparam, ipntr, workd, workl, lworkl, &info, 0);
386 else
387 callFortran.SAUPD(&ido, 'G', localSize, "LM", numEigen, tolEigenSolve, resid, NCV, v,
388 localSize, iparam, ipntr, workd, workl, lworkl, &info, 0);
389#else
390 callFortran.SAUPD(&ido, 'G', localSize, "LM", numEigen, tolEigenSolve, resid, NCV, v,
391 localSize, iparam, ipntr, workd, workl, lworkl, &info, 0);
392#endif
393
394 if (ido == -1) {
395 // Apply the mass matrix
396 v3.ResetView(workd + ipntr[0] - 1);
397 v1.ResetView(vTmp);
398 timeMassOp -= MyWatch.WallTime();
399 if (M)
400 M->Apply(v3, v1);
401 else
402 memcpy(v1.Values(), v3.Values(), localSize*sizeof(double));
403 timeMassOp += MyWatch.WallTime();
404 massOp += 1;
405 if ((orthoVec) && (verbose > 3)) {
406 // Check the orthogonality
407 double maxDot = myVerify.errorOrthogonality(orthoVec, &v1, 0);
408 if (myPid == 0) {
409 cout << " Maximum Euclidean dot product against orthogonal space (Before Solve) = ";
410 cout << maxDot << endl;
411 }
412 }
413 // Solve the stiffness problem
414 v2.ResetView(workd + ipntr[1] - 1);
415 timeStifOp -= MyWatch.WallTime();
416 K->ApplyInverse(v1, v2);
417 timeStifOp += MyWatch.WallTime();
418 stifOp += 1;
419 // Project the solution vector if needed
420 // Note: Use mvz as workspace
421 if (orthoVec) {
422 Epetra_Vector Mv2(View, v2.Map(), mvz);
423 if (M)
424 M->Apply(v2, Mv2);
425 else
426 memcpy(Mv2.Values(), v2.Values(), localSize*sizeof(double));
427 modalTool.massOrthonormalize(v2, Mv2, M, *orthoVec, 1, 1);
428 }
429 if ((orthoVec) && (verbose > 3)) {
430 // Check the orthogonality
431 double maxDot = myVerify.errorOrthogonality(orthoVec, &v2, M);
432 if (myPid == 0) {
433 cout << " Maximum M-dot product against orthogonal space (After Solve) = ";
434 cout << maxDot << endl;
435 }
436 }
437 continue;
438 } // if (ido == -1)
439
440 if (ido == 1) {
441 // Solve the stiffness problem
442 v1.ResetView(workd + ipntr[2] - 1);
443 v2.ResetView(workd + ipntr[1] - 1);
444 if ((orthoVec) && (verbose > 3)) {
445 // Check the orthogonality
446 double maxDot = myVerify.errorOrthogonality(orthoVec, &v1, 0);
447 if (myPid == 0) {
448 cout << " Maximum Euclidean dot product against orthogonal space (Before Solve) = ";
449 cout << maxDot << endl;
450 }
451 }
452 timeStifOp -= MyWatch.WallTime();
453 K->ApplyInverse(v1, v2);
454 timeStifOp += MyWatch.WallTime();
455 stifOp += 1;
456 // Project the solution vector if needed
457 // Note: Use mvz as workspace
458 if (orthoVec) {
459 Epetra_Vector Mv2(View, v2.Map(), mvz);
460 if (M)
461 M->Apply(v2, Mv2);
462 else
463 memcpy(Mv2.Values(), v2.Values(), localSize*sizeof(double));
464 modalTool.massOrthonormalize(v2, Mv2, M, *orthoVec, 1, 1);
465 }
466 if ((orthoVec) && (verbose > 3)) {
467 // Check the orthogonality
468 double maxDot = myVerify.errorOrthogonality(orthoVec, &v2, M);
469 if (myPid == 0) {
470 cout << " Maximum M-dot product against orthogonal space (After Solve) = ";
471 cout << maxDot << endl;
472 }
473 }
474 continue;
475 } // if (ido == 1)
476
477 if (ido == 2) {
478 // Apply the mass matrix
479 v1.ResetView(workd + ipntr[0] - 1);
480 v2.ResetView(workd + ipntr[1] - 1);
481 timeMassOp -= MyWatch.WallTime();
482 if (M)
483 M->Apply(v1, v2);
484 else
485 memcpy(v2.Values(), v1.Values(), localSize*sizeof(double));
486 timeMassOp += MyWatch.WallTime();
487 massOp += 1;
488 continue;
489 } // if (ido == 2)
490
491 if (ido == 4) {
492 timeResidual -= MyWatch.WallTime();
493 // Copy the main diagonal of T
494 memcpy(dd, workl + NCV + ipntr[4] - 1, NCV*sizeof(double));
495 // Copy the lower diagonal of T
496 memcpy(ee, workl + ipntr[4], (NCV-1)*sizeof(double));
497 // Compute the eigenpairs of the tridiagonal matrix
498 zz = workl + 4*NCV;
499 workt = workl + 4*NCV + NCV*NCV;
500 callFortran.STEQR('I', NCV, dd, ee, zz, NCV, workt, &info);
501 if (info != 0) {
502 if (localVerbose > 0) {
503 cerr << endl;
504 cerr << " Error with DSTEQR, info = " << info << endl;
505 cerr << endl;
506 }
507 break;
508 }
509 // dd contains the eigenvalues in ascending order
510 // Check the residual of the proposed eigenvectors of (K, M)
511 int ii, jz;
512 iparam[4] = 0;
513 for (jz = 0; jz < NCV; jz += loopZ) {
514 int colZ = (jz + loopZ < NCV) ? loopZ : NCV - jz;
515 callBLAS.GEMM('N', 'N', localSize, colZ, NCV, 1.0, v, localSize,
516 zz + jz*NCV, NCV, 0.0, vz, localSize);
517 // Form the residuals
518 if (M)
519 M->Apply(approxEV, MapproxEV);
520 K->Apply(approxEV, KapproxEV);
521 for (ii = 0; ii < colZ; ++ii) {
522 callBLAS.AXPY(localSize, -1.0/dd[ii+jz], MapproxEV.Values() + ii*localSize,
523 KapproxEV.Values() + ii*localSize);
524 }
525 // Compute the norms of the residuals
526 if (vectWeight) {
527 KapproxEV.NormWeighted(*vectWeight, normR + jz);
528 }
529 else {
530 KapproxEV.Norm2(normR + jz);
531 }
532 // Scale the norms of residuals with the eigenvalues
533 for (ii = 0; ii < colZ; ++ii) {
534 normR[ii+jz] = normR[ii+jz]*dd[ii+jz];
535 }
536 // Put the number of converged pairs in iparam[5-1]
537 for (ii=0; ii<colZ; ++ii) {
538 if (normR[ii+jz] < tolEigenSolve)
539 iparam[4] += 1;
540 }
541 }
542 timeResidual += MyWatch.WallTime();
543 numResidual += NCV;
544 outerIter += 1;
545 if (localVerbose > 0) {
546 cout << " Iteration " << outerIter;
547 cout << " - Number of converged eigenvalues " << iparam[4] << endl;
548 }
549 if (localVerbose > 2) {
550 memcpy(resHistory + historyCount, normR, NCV*sizeof(double));
551 historyCount += NCV;
552 }
553 if (localVerbose > 1) {
554 cout.precision(2);
555 cout.setf(ios::scientific, ios::floatfield);
556 for (ii=0; ii < NCV; ++ii) {
557 cout << " Iteration " << outerIter;
558 cout << " - Scaled Norm of Residual " << ii << " = " << normR[ii] << endl;
559 }
560 cout << endl;
561 cout.precision(2);
562 for (ii = 0; ii < NCV; ++ii) {
563 cout << " Iteration " << outerIter << " - Ritz eigenvalue " << ii;
564 cout.setf((fabs(dd[ii]) > 100) ? ios::scientific : ios::fixed, ios::floatfield);
565 cout << " = " << 1.0/dd[ii] << endl;
566 }
567 cout << endl;
568 }
569 } // if (ido == 4)
570
571 } // while (ido != 99)
572 timeOuterLoop += MyWatch.WallTime();
573 highMem = (highMem > currentSize()) ? highMem : currentSize();
574
575 if (info < 0) {
576 if (myPid == 0) {
577 cerr << endl;
578 cerr << " Error with DSAUPD, info = " << info << endl;
579 cerr << endl;
580 }
581 }
582 else {
583 // Get the eigenvalues
584 timePostProce -= MyWatch.WallTime();
585 int ii, jj;
586 double *pointer = workl + 4*NCV + NCV*NCV;
587 for (ii=0; ii < localSize; ii += 3) {
588 int nRow = (ii + 3 < localSize) ? 3 : localSize - ii;
589 for (jj=0; jj<NCV; ++jj)
590 memcpy(pointer + jj*nRow, v + ii + jj*localSize, nRow*sizeof(double));
591 callBLAS.GEMM('N', 'N', nRow, NCV, NCV, 1.0, pointer, nRow, zz, NCV,
592 0.0, Q.Values() + ii, localSize);
593 }
594 // Put the converged eigenpairs at the beginning
595 knownEV = 0;
596 for (ii=0; ii < NCV; ++ii) {
597 if (normR[ii] < tolEigenSolve) {
598 lambda[knownEV] = 1.0/dd[ii];
599 memcpy(Q.Values()+knownEV*localSize, Q.Values()+ii*localSize, localSize*sizeof(double));
600 knownEV += 1;
601 if (knownEV == Q.NumVectors())
602 break;
603 }
604 }
605 // Sort the eigenpairs
606 if (knownEV > 0) {
607 mySort.sortScalars_Vectors(knownEV, lambda, Q.Values(), localSize);
608 }
609 timePostProce += MyWatch.WallTime();
610 } // if (info < 0)
611
612 if (info == 0) {
613 orthoOp = iparam[11-1];
614 }
615
616 delete[] wI;
617 delete[] wD;
618 delete[] wD2;
619 if (vectWeight)
620 delete vectWeight;
621
622 return (info == 0) ? knownEV : info;
623
624}
625
626
627void ModifiedARPACKm3::initializeCounters() {
628
629 historyCount = 0;
630 if (resHistory) {
631 delete[] resHistory;
632 resHistory = 0;
633 }
634
635 memRequested = 0.0;
636 highMem = 0.0;
637
638 massOp = 0;
639 numResidual = 0;
640 orthoOp = 0;
641 outerIter = 0;
642 stifOp = 0;
643
644 timeMassOp = 0.0;
645 timeOuterLoop = 0.0;
646 timePostProce = 0.0;
647 timeResidual = 0.0;
648 timeStifOp = 0.0;
649
650}
651
652
653void ModifiedARPACKm3::algorithmInfo() const {
654
655 int myPid = MyComm.MyPID();
656
657 if (myPid ==0) {
658 cout << " Algorithm: ARPACK (Mode 3, modified such that user checks convergence)\n";
659 }
660
661}
662
663
664void ModifiedARPACKm3::memoryInfo() const {
665
666 int myPid = MyComm.MyPID();
667
668 double maxHighMem = 0.0;
669 double tmp = highMem;
670 MyComm.MaxAll(&tmp, &maxHighMem, 1);
671
672 double maxMemRequested = 0.0;
673 tmp = memRequested;
674 MyComm.MaxAll(&tmp, &maxMemRequested, 1);
675
676 if (myPid == 0) {
677 cout.precision(2);
678 cout.setf(ios::fixed, ios::floatfield);
679 cout << " Memory requested per processor by the eigensolver = (EST) ";
680 cout.width(6);
681 cout << maxMemRequested << " MB " << endl;
682 cout << endl;
683 cout << " High water mark in eigensolver = (EST) ";
684 cout.width(6);
685 cout << maxHighMem << " MB " << endl;
686 cout << endl;
687 }
688
689}
690
691
692void ModifiedARPACKm3::historyInfo() const {
693
694 if (resHistory) {
695 int j;
696 cout << " Residuals\n";
697 cout << endl;
698 cout.precision(4);
699 cout.setf(ios::scientific, ios::floatfield);
700 for (j = 0; j < historyCount; ++j) {
701 cout << resHistory[j] << endl;
702 }
703 cout << endl;
704 }
705
706}
707
708
709void ModifiedARPACKm3::operationInfo() const {
710
711 int myPid = MyComm.MyPID();
712
713 if (myPid == 0) {
714 cout << " --- Operations ---\n\n";
715 cout << " Total number of mass matrix multiplications = ";
716 cout.width(9);
717 cout << massOp << endl;
718 cout << " Total number of orthogonalizations = ";
719 cout.width(9);
720 cout << orthoOp << endl;
721 cout << " Total number of stiffness matrix operations = ";
722 cout.width(9);
723 cout << stifOp << endl;
724 cout << " Total number of computed eigen-residuals = ";
725 cout.width(9);
726 cout << numResidual << endl;
727 cout << endl;
728 cout << " Total number of outer iterations = ";
729 cout.width(9);
730 cout << outerIter << endl;
731 cout << endl;
732 }
733
734}
735
736
737void ModifiedARPACKm3::timeInfo() const {
738
739 int myPid = MyComm.MyPID();
740
741 if (myPid == 0) {
742 cout << " --- Timings ---\n\n";
743 cout.setf(ios::fixed, ios::floatfield);
744 cout.precision(2);
745 cout << " Total time for outer loop = ";
746 cout.width(9);
747 cout << timeOuterLoop << " s" << endl;
748 cout << " Time for mass matrix operations = ";
749 cout.width(9);
750 cout << timeMassOp << " s ";
751 cout.width(5);
752 cout << 100*timeMassOp/timeOuterLoop << " %\n";
753 cout << " Time for stiffness matrix solves = ";
754 cout.width(9);
755 cout << timeStifOp << " s ";
756 cout.width(5);
757 cout << 100*timeStifOp/timeOuterLoop << " %\n";
758 cout << " Time for residual computations = ";
759 cout.width(9);
760 cout << timeResidual << " s ";
761 cout.width(5);
762 cout << 100*timeResidual/timeOuterLoop << " %\n";
763 cout << endl;
764 cout << " Total time for post-processing = ";
765 cout.width(9);
766 cout << timePostProce << " s\n";
767 cout << endl;
768 } // if (myId == 0)
769
770}
771
772