19 #include "CheckingTools.h"
22 CheckingTools::CheckingTools(
const Epetra_Comm &_Comm) :
35 int xc = (X) ? X->NumVectors() : 0;
36 int rc = (R) ? R->NumVectors() : 0;
42 for (i = 0; i < rc; ++i) {
45 M->
Apply(*((*R)(i)), MRi);
49 for (j = 0; j < xc; ++j) {
51 (*X)(j)->Norm2(&normXj);
52 (*X)(j)->Dot(MRi, &dot);
53 dot = fabs(dot)/(normMR*normXj);
54 maxDot = (dot > maxDot) ? dot : maxDot;
70 int xc = (X) ? X->NumVectors() : 0;
75 for (i = 0; i < xc; ++i) {
78 M->
Apply(*((*X)(i)), MXi);
80 for (j = 0; j < xc; ++j) {
81 (*X)(j)->Dot(MXi, &dot);
82 dot = (i == j) ? fabs(dot - 1.0) : fabs(dot);
83 maxDot = (dot > maxDot) ? dot : maxDot;
101 int xc = (X) ? X->NumVectors() : 0;
102 int mxc = (MX) ? MX->NumVectors() : 0;
104 if ((xc != mxc) || (xc*mxc == 0))
108 double maxCoeffX = 0.0;
109 for (i = 0; i < xc; ++i) {
111 (*MX)(i)->NormInf(&tmp);
112 maxCoeffX = (tmp > maxCoeffX) ? tmp : maxCoeffX;
115 for (i = 0; i < xc; ++i) {
118 M->
Apply(*((*X)(i)), MtimesXi);
119 MtimesXi.Update(-1.0, *((*MX)(i)), 1.0);
121 MtimesXi.NormInf(&diff);
122 maxDiff = (diff > maxDiff) ? diff : maxDiff;
125 return (maxCoeffX == 0.0) ? maxDiff : maxDiff/maxCoeffX;
134 int myPid = MyComm.MyPID();
136 int qr = Q.MyLength();
137 int qc = Q.NumVectors();
138 int qexc = Qex.NumVectors();
140 double *mQ =
new (nothrow)
double[qr];
146 double *z =
new (nothrow)
double[qexc*qc];
157 for (j=0; j<qc; ++j) {
163 memcpy(mQ, Qj.Values(), qr*
sizeof(double));
165 colJ.Multiply(
'T',
'N', 1.0, Qex, MQ, 0.0);
171 int svSize = (qc > qexc) ? qexc : qc;
172 double *sv =
new (nothrow)
double[svSize];
180 int lwork = (qexc > qc) ? qexc + 5*qc : qc + 5*qexc;
181 double *work =
new (nothrow)
double[lwork];
190 call.
GESVD(
'N',
'N',qexc,qc,QextMQ.Values(),qexc,sv,0,qc,0,qc,work,&lwork,&info);
200 cerr <<
" In DGESVD, argument " << -info <<
" has an illegal value\n";
210 cerr <<
" In DGESVD, DBSQR did not converge (" << info <<
").\n";
221 cout <<
" --- Principal angles between eigenspaces ---\n";
223 cout <<
" Reference space built with " << Qex.NumVectors() <<
" vectors." << endl;
224 cout <<
" Dimension of computed space: " << Q.NumVectors() << endl;
226 cout.setf(ios::scientific, ios::floatfield);
228 cout <<
" Smallest singular value = " << sv[0] << endl;
229 cout <<
" Largest singular value = " << sv[svSize-1] << endl;
231 cout <<
" Smallest angle between subspaces (rad) = ";
232 cout << ((sv[0] > 1.0) ? 0.0 : asin(sqrt(1.0 - sv[0]*sv[0]))) << endl;
233 cout <<
" Largest angle between subspaces (rad) = ";
234 cout << ((sv[0] > 1.0) ? 0.0 : asin(sqrt(1.0 - sv[svSize-1]*sv[svSize-1]))) << endl;
247 double *normWeight)
const {
249 if ((K == 0) || (lambda == 0))
252 int myPid = MyComm.MyPID();
254 int qr = Q.MyLength();
255 int qc = Q.NumVectors();
257 double *work =
new (nothrow)
double[2*qr];
263 cout <<
" --- Norms of residuals for computed eigenmodes ---\n";
265 cout <<
" Eigenvalue";
267 cout <<
" User Norm Scaled User N.";
268 cout <<
" 2-Norm Scaled 2-Nor.\n";
275 double maxUserNorm = 0.0;
276 double minUserNorm = 1.0e+100;
277 double maxL2Norm = 0.0;
278 double minL2Norm = 1.0e+100;
282 for (j=0; j<qc; ++j) {
288 memcpy(MQ.Values(), Qj.Values(), qr*
sizeof(double));
290 KQ.Update(-lambda[j], MQ, 1.0);
292 double residualL2 = 0.0;
293 KQ.Norm2(&residualL2);
295 double residualUser = 0.0;
298 KQ.NormWeighted(vectWeight, &residualUser);
305 cout.setf(ios::scientific, ios::floatfield);
306 cout << j+1 <<
". " << lambda[j] <<
" ";
308 cout << residualUser <<
" ";
309 cout << ((lambda[j] == 0.0) ? 0.0 : residualUser/lambda[j]) <<
" ";
311 cout << residualL2 <<
" " << ((lambda[j] == 0.0) ? 0.0 : residualL2/lambda[j]) <<
" ";
315 if (lambda[j] > 0.0) {
316 maxL2Norm = (residualL2/lambda[j] > maxL2Norm) ? residualL2/lambda[j] : maxL2Norm;
317 minL2Norm = (residualL2/lambda[j] < minL2Norm) ? residualL2/lambda[j] : minL2Norm;
319 maxUserNorm = (residualUser/lambda[j] > maxUserNorm) ? residualUser/lambda[j]
321 minUserNorm = (residualUser/lambda[j] < minUserNorm) ? residualUser/lambda[j]
331 cout <<
" >> Minimum scaled user-norm of residuals = " << minUserNorm << endl;
332 cout <<
" >> Maximum scaled user-norm of residuals = " << maxUserNorm << endl;
335 cout <<
" >> Minimum scaled L2 norm of residuals = " << minL2Norm << endl;
336 cout <<
" >> Maximum scaled L2 norm of residuals = " << maxL2Norm << endl;
350 if ((K == 0) || (lambda == 0) || (Msolver == 0))
353 int myPid = MyComm.MyPID();
355 int qr = Q.MyLength();
356 int qc = Q.NumVectors();
358 double *work =
new (nothrow)
double[2*qr];
364 cout <<
" --- Norms of residuals for computed eigenmodes ---\n";
366 cout <<
" Eigenvalue";
367 cout <<
" M^{-1} N. Sca. M^{-1} N.";
368 cout <<
" 2-Norm Scaled 2-Nor.\n";
375 double maxMinvNorm = 0.0;
376 double minMinvNorm = 1.0e+100;
377 double maxL2Norm = 0.0;
378 double minL2Norm = 1.0e+100;
382 for (j=0; j<qc; ++j) {
388 memcpy(MQ.Values(), Qj.Values(), qr*
sizeof(double));
390 KQ.Update(-lambda[j], MQ, 1.0);
392 double residualL2 = 0.0;
393 KQ.Norm2(&residualL2);
395 double residualMinv = 0.0;
397 KQ.Dot(MQ, &residualMinv);
398 residualMinv = sqrt(fabs(residualMinv));
404 cout.setf(ios::scientific, ios::floatfield);
405 cout << j+1 <<
". " << lambda[j] <<
" ";
406 cout << residualMinv <<
" ";
407 cout << ((lambda[j] == 0.0) ? 0.0 : residualMinv/lambda[j]) <<
" ";
408 cout << residualL2 <<
" " << ((lambda[j] == 0.0) ? 0.0 : residualL2/lambda[j]) <<
" ";
412 if (lambda[j] > 0.0) {
413 maxL2Norm = (residualL2/lambda[j] > maxL2Norm) ? residualL2/lambda[j] : maxL2Norm;
414 minL2Norm = (residualL2/lambda[j] < minL2Norm) ? residualL2/lambda[j] : minL2Norm;
415 maxMinvNorm = (residualMinv/lambda[j] > maxMinvNorm) ? residualMinv/lambda[j]
417 minMinvNorm = (residualMinv/lambda[j] < minMinvNorm) ? residualMinv/lambda[j]
425 cout <<
" >> Minimum scaled M^{-1}-norm of residuals = " << minMinvNorm << endl;
426 cout <<
" >> Maximum scaled M^{-1}-norm of residuals = " << maxMinvNorm << endl;
428 cout <<
" >> Minimum scaled L2 norm of residuals = " << minL2Norm << endl;
429 cout <<
" >> Maximum scaled L2 norm of residuals = " << maxL2Norm << endl;
439 int CheckingTools::errorLambda(
double *continuous,
double *discrete,
int numDiscrete,
440 double *lambda,
int nev)
const {
442 int myPid = MyComm.MyPID();
448 int *used =
new (nothrow)
int[numDiscrete + nev];
453 int *bestMatch = used + numDiscrete;
458 call.
LAMCH(
'E', eps);
460 double gap = Epetra_MaxDouble;
461 for (i=0; i<numDiscrete; ++i) {
463 for (j = i; j < numDiscrete; ++j) {
464 if (discrete[j] > (1.0 + 10.0*eps)*discrete[i]) {
465 double tmp = (discrete[j] - discrete[i])/discrete[i];
466 gap = (tmp < gap) ? tmp : gap;
472 for (i=0; i<nev; ++i) {
476 for (i=0; i<nev; ++i) {
477 if (lambda[i] < continuous[0]) {
480 bestMatch[i] = (i == 0) ? 0 : bestMatch[i-1] + 1;
481 int jStart = bestMatch[i];
482 for (j = jStart; j < numDiscrete; ++j) {
483 double diff = fabs(lambda[i]-discrete[j]);
484 if (diff < 0.5*gap*lambda[i]) {
489 used[bestMatch[i]] = i;
495 cout <<
" --- Relative errors on eigenvalues ---\n";
497 cout <<
" Exact Cont. Exact Disc. Computed ";
498 cout <<
" Alg. Err. Mesh Err.\n";
502 for (i=0; i<nev; ++i) {
503 if (bestMatch[i] == -1) {
505 cout <<
" ************** ************** ";
507 cout.setf(ios::scientific, ios::floatfield);
509 cout <<
" ********* *********" << endl;
515 double lastDiscrete = 0.0;
516 for (i=0; i<numDiscrete; ++i) {
517 if ((iCount == nev) && (discrete[i] > lastDiscrete)) {
522 lastDiscrete = discrete[i];
528 cout.setf(ios::scientific, ios::floatfield);
529 cout << continuous[i] <<
" " << discrete[i] <<
" ";
530 cout <<
"************** ********* ";
532 cout << fabs(continuous[i]-discrete[i])/continuous[i] << endl;
537 lastDiscrete = discrete[i];
543 cout.setf(ios::scientific, ios::floatfield);
544 cout << continuous[i] <<
" " << discrete[i] <<
" " << lambda[used[i]] <<
" ";
546 cout << fabs(lambda[used[i]]-discrete[i])/discrete[i] <<
" ";
547 cout << fabs(continuous[i]-discrete[i])/continuous[i] << endl;
560 int CheckingTools::inputArguments(
const int &numEigen,
const Epetra_Operator *K,
574 int myPid = MyComm.MyPID();
578 cerr <<
"\n !!! The matrix K to analyze has not been specified !!! \n\n";
587 if ((mGlobal != kGlobal) || (mLocal != kLocal)) {
590 cerr <<
" !!! The maps for the matrice K and the mass M are different !!!\n";
602 if ((pGlobal != kGlobal) || (pLocal != kLocal)) {
605 cerr <<
" !!! The maps for the matrice K and the preconditioner P are different !!!\n";
615 cerr <<
"\n !!! The maps for the vectors and the matrix are different !!! \n\n";
620 if (Q.NumVectors() < numEigen) {
623 cerr <<
" !!! The number of eigenvalues is too large for the space allocated !!! \n\n";
624 cerr <<
" The recommended size for " << numEigen <<
" eigenvalues is ";
625 cerr << minSize << endl;
631 if (Q.NumVectors() < minSize) {
634 cerr <<
" !!! The space allocated is too small for the number of eigenvalues";
635 cerr <<
" and the size of blocks specified !!! \n";
636 cerr <<
" The recommended size for " << numEigen <<
" eigenvalues is ";
637 cerr << minSize << endl;
int ResetView(double *Values_in)
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const =0
void GESVD(const char JOBU, const char JOBVT, const int M, const int N, float *A, const int LDA, float *S, float *U, const int LDU, float *VT, const int LDVT, float *WORK, const int *LWORK, int *INFO) const
virtual const Epetra_Map & OperatorDomainMap() const =0
virtual int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const =0
void LAMCH(const char CMACH, float &T) const