Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ModeLaplace2DQ1.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 //**************************************************************************
11 //
12 // NOTICE
13 //
14 // This software is a result of the research described in the report
15 //
16 // " A comparison of algorithms for modal analysis in the absence
17 // of a sparse direct method", P. ArbenZ, R. Lehoucq, and U. Hetmaniuk,
18 // Sandia National Laboratories, Technical report SAND2003-1028J.
19 //
20 // It is based on the Epetra, AztecOO, and ML packages defined in the Trilinos
21 // framework ( http://software.sandia.gov/trilinos/ ).
22 //
23 // The distribution of this software follows also the rules defined in Trilinos.
24 // This notice shall be marked on anY reproduction of this software, in whole or
25 // in part.
26 //
27 // This program is distributed in the hope that it will be useful, but
28 // WITHOUT ANY WARRANTY; without even the implied warranty of
29 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 //
31 // Code Authors: U. Hetmaniuk (ulhetma@sandia.gov), R. Lehoucq (rblehou@sandia.gov)
32 //
33 //**************************************************************************
34 
35 #include "ModeLaplace2DQ1.h"
36 #include "Teuchos_Assert.hpp"
37 
38 
39 const int ModeLaplace2DQ1::dofEle = 4;
40 const int ModeLaplace2DQ1::maxConnect = 9;
41 #ifndef M_PI
42 const double ModeLaplace2DQ1::M_PI = 3.14159265358979323846;
43 #endif
44 
45 
46 ModeLaplace2DQ1::ModeLaplace2DQ1(const Epetra_Comm &_Comm, double _Lx, int _nX,
47  double _Ly, int _nY)
48  : myVerify(_Comm),
49  MyComm(_Comm),
50  mySort(),
51  Map(0),
52  K(0),
53  M(0),
54  Lx(_Lx),
55  nX(_nX),
56  Ly(_Ly),
57  nY(_nY),
58  x(0),
59  y(0)
60  {
61 
62  preProcess();
63 
64 }
65 
66 
67 ModeLaplace2DQ1::~ModeLaplace2DQ1() {
68 
69  if (Map)
70  delete Map;
71  Map = 0;
72 
73  if (K)
74  delete K;
75  K = 0;
76 
77  if (M)
78  delete M;
79  M = 0;
80 
81  if (x)
82  delete[] x;
83  x = 0;
84 
85  if (y)
86  delete[] y;
87  y = 0;
88 
89 }
90 
91 
92 void ModeLaplace2DQ1::preProcess() {
93 
94  // Create the distribution of equations across processors
95  makeMap();
96 
97  // Count the number of elements touched by this processor
98  bool *isTouched = new bool[nX*nY];
99  int i, j;
100  for (j = 0; j < nY; ++j)
101  for (i=0; i<nX; ++i)
102  isTouched[i + j*nX] = false;
103 
104  int numEle = countElements(isTouched);
105 
106  // Create the mesh
107  int *elemTopo = new int[dofEle*numEle];
108  makeMyElementsTopology(elemTopo, isTouched);
109 
110  delete[] isTouched;
111 
112  // Get the number of nonZeros per row
113  int localSize = Map->NumMyElements();
114  int *numNz = new int[localSize];
115  int *connectivity = new int[localSize*maxConnect];
116  makeMyConnectivity(elemTopo, numEle, connectivity, numNz);
117 
118  // Make the stiffness matrix
119  makeStiffness(elemTopo, numEle, connectivity, numNz);
120 
121  // Assemble the mass matrix
122  makeMass(elemTopo, numEle, connectivity, numNz);
123 
124  // Free some memory
125  delete[] elemTopo;
126  delete[] numNz;
127  delete[] connectivity;
128 
129  // Get the geometrical coordinates of the managed nodes
130  double hx = Lx/nX;
131  double hy = Ly/nY;
132 
133  x = new double[localSize];
134  y = new double[localSize];
135 
136  for (j=0; j<nY-1; ++j) {
137  for (i=0; i<nX-1; ++i) {
138  int node = i + j*(nX-1);
139  if (Map->LID(node) > -1) {
140  x[Map->LID(node)] = (i+1)*hx;
141  y[Map->LID(node)] = (j+1)*hy;
142  }
143  }
144  }
145 
146 }
147 
148 
149 void ModeLaplace2DQ1::makeMap() {
150 
151  int numProc = MyComm.NumProc();
152  int globalSize = (nX - 1)*(nY - 1);
153  assert(globalSize > numProc);
154 
155 #ifdef _USE_CHACO
156  // Use the partitioner Chaco to distribute the unknowns
157  int *start = new int[globalSize+1];
158  memset(start, 0, (globalSize+1)*sizeof(int));
159 
160  int i, j;
161  for (j=0; j<nY-1; ++j) {
162  for (i=0; i<nX-1; ++i) {
163  int node = i + j*(nX-1);
164  int connect = 1;
165  connect *= ((i == 0) || (i == nX-2)) ? 2 : 3;
166  connect *= ((j == 0) || (j == nY-2)) ? 2 : 3;
167  // Don't count the node itself for Chaco
168  start[node+1] = connect - 1;
169  }
170  }
171 
172  for (i = 0; i < globalSize; ++i)
173  start[i+1] += start[i];
174 
175  int *adjacency = new int[start[globalSize]];
176  memset(adjacency, 0, start[globalSize]*sizeof(int));
177 
178  int *elemTopo = new int[dofEle];
179  for (j=0; j<nY; ++j) {
180  for (i=0; i<nX; ++i) {
181  int bottomLeft = i-1 + (j-1)*(nX-1);
182  elemTopo[0] = ((i==0) || (j==0)) ? -1 : bottomLeft;
183  elemTopo[1] = ((i==nX-1) || (j==0)) ? -1 : bottomLeft + 1;
184  elemTopo[2] = ((i==nX-1) || (j==nY-1)) ? -1 : bottomLeft + nX;
185  elemTopo[3] = ((i==0) || (j==nY-1)) ? -1 : bottomLeft + nX - 1;
186  for (int iD = 0; iD < dofEle; ++iD) {
187  if (elemTopo[iD] == -1)
188  continue;
189  for (int jD = 0; jD < dofEle; ++jD) {
190  int neighbor = elemTopo[jD];
191  // Don't count the node itself for Chaco
192  if ((neighbor == -1) || (iD == jD))
193  continue;
194  // Check if this neighbor is already stored
195  for (int l = start[elemTopo[iD]]; l < start[elemTopo[iD]+1]; ++l) {
196  // Note that Chaco uses a Fortran numbering
197  if (adjacency[l] == neighbor + 1)
198  break;
199  if (adjacency[l] == 0) {
200  // Store the node ID
201  // Note that Chaco uses a Fortran numbering
202  adjacency[l] = elemTopo[jD] + 1;
203  break;
204  }
205  } // for (int l = start[elemTopo[iD]]; l < start[elemTopo[iD]+1]; ++l)
206  } // for (int jD = 0; jD < dofEle; ++jD)
207  } // for (int iD = 0; iD < dofEle; ++iD)
208  }
209  }
210  delete[] elemTopo;
211 
212  int nDir[3];
213  nDir[0] = numProc;
214  nDir[1] = 0;
215  nDir[2] = 0;
216  short int *partition = new short int[globalSize];
217  // Call Chaco to partition the matrix
218  interface(globalSize, start, adjacency, 0, 0, 0, 0, 0, 0, 0,
219  partition, 1, 1, nDir, 0, 1, 1, 1, 250, 1, 0.001, 7654321L);
220  // Define the Epetra_Map
221  int localSize = 0;
222  int myPid = MyComm.MyPID();
223  for (i = 0; i < globalSize; ++i) {
224  if (partition[i] == myPid)
225  localSize += 1;
226  }
227  int *myRows = new int[localSize];
228  localSize = 0;
229  for (i = 0; i < globalSize; ++i) {
230  if (partition[i] == myPid) {
231  myRows[localSize] = i;
232  localSize +=1 ;
233  }
234  }
235  delete[] partition;
236  delete[] adjacency;
237  delete[] start;
238  Map = new Epetra_Map(globalSize, localSize, myRows, 0, MyComm);
239  delete[] myRows;
240 #else
241  // Create a uniform distribution of the unknowns across processors
242  Map = new Epetra_Map(globalSize, 0, MyComm);
243 #endif
244 
245 }
246 
247 
248 int ModeLaplace2DQ1::countElements(bool *isTouched) {
249 
250  // This routine counts and flags the elements that contain the nodes
251  // on this processor.
252 
253  int i, j;
254  int numEle = 0;
255 
256  for (j=0; j<nY; ++j) {
257  for (i=0; i<nX; ++i) {
258  isTouched[i+j*nX] = false;
259  int bottomLeft = i-1 + (j-1)*(nX-1);
260  int node;
261  node = ((i==0) || (j==0)) ? -1 : bottomLeft;
262  if ((node > -1) && (Map->LID(node) > -1)) {
263  isTouched[i+j*nX] = true;
264  numEle += 1;
265  continue;
266  }
267  node = ((i==nX-1) || (j==0)) ? -1 : bottomLeft + 1;
268  if ((node > -1) && (Map->LID(node) > -1)) {
269  isTouched[i+j*nX] = true;
270  numEle += 1;
271  continue;
272  }
273  node = ((i==nX-1) || (j==nY-1)) ? -1 : bottomLeft + nX;
274  if ((node > -1) && (Map->LID(node) > -1)) {
275  isTouched[i+j*nX] = true;
276  numEle += 1;
277  continue;
278  }
279  node = ((i==0) || (j==nY-1)) ? -1 : bottomLeft + nX - 1;
280  if ((node > -1) && (Map->LID(node) > -1)) {
281  isTouched[i+j*nX] = true;
282  numEle += 1;
283  continue;
284  }
285  }
286  }
287 
288  return numEle;
289 
290 }
291 
292 
293 void ModeLaplace2DQ1::makeMyElementsTopology(int *elemTopo, bool *isTouched) {
294 
295  // Create the element topology for the elements containing nodes for this processor
296  // Note: Put the flag -1 when the node has a Dirichlet boundary condition
297 
298  int i, j;
299  int numEle = 0;
300 
301  for (j=0; j<nY; ++j) {
302  for (i=0; i<nX; ++i) {
303  if (isTouched[i + j*nX] == false)
304  continue;
305  int bottomLeft = i-1 + (j-1)*(nX-1);
306  elemTopo[dofEle*numEle] = ((i==0) || (j==0)) ? -1 : bottomLeft;
307  elemTopo[dofEle*numEle+1] = ((i==nX-1) || (j==0)) ? -1 : bottomLeft + 1;
308  elemTopo[dofEle*numEle+2] = ((i==nX-1) || (j==nY-1)) ? -1 : bottomLeft + nX;
309  elemTopo[dofEle*numEle+3] = ((i==0) || (j==nY-1)) ? -1 : bottomLeft + nX - 1;
310  numEle += 1;
311  }
312  }
313 
314 }
315 
316 
317 void ModeLaplace2DQ1::makeMyConnectivity(int *elemTopo, int numEle, int *connectivity,
318  int *numNz) {
319 
320  // This routine creates the connectivity of each managed node
321  // from the element topology.
322 
323  int i, j;
324  int localSize = Map->NumMyElements();
325 
326  for (i=0; i<localSize; ++i) {
327  numNz[i] = 0;
328  for (j=0; j<maxConnect; ++j) {
329  connectivity[i*maxConnect + j] = -1;
330  }
331  }
332 
333  for (i=0; i<numEle; ++i) {
334  for (j=0; j<dofEle; ++j) {
335  if (elemTopo[dofEle*i+j] == -1)
336  continue;
337  int node = Map->LID(elemTopo[dofEle*i+j]);
338  if (node > -1) {
339  int k;
340  for (k=0; k<dofEle; ++k) {
341  int neighbor = elemTopo[dofEle*i+k];
342  if (neighbor == -1)
343  continue;
344  // Check if this neighbor is already stored
345  int l;
346  for (l=0; l<maxConnect; ++l) {
347  if (neighbor == connectivity[node*maxConnect + l])
348  break;
349  if (connectivity[node*maxConnect + l] == -1) {
350  connectivity[node*maxConnect + l] = neighbor;
351  numNz[node] += 1;
352  break;
353  }
354  } // for (l = 0; l < maxConnect; ++l)
355  } // for (k = 0; k < dofEle; ++k)
356  } // if (node > -1)
357  } // for (j = 0; j < dofEle; ++j)
358  } // for (i = 0; i < numEle; ++i)
359 
360 }
361 
362 
363 void ModeLaplace2DQ1::makeStiffness(int *elemTopo, int numEle, int *connectivity,
364  int *numNz) {
365 
366  // Create Epetra_Matrix for stiffness
367  K = new Epetra_CrsMatrix(Copy, *Map, numNz);
368 
369  int i;
370  int localSize = Map->NumMyElements();
371 
372  double *values = new double[maxConnect];
373  for (i=0; i<maxConnect; ++i)
374  values[i] = 0.0;
375 
376  for (i=0; i<localSize; ++i) {
377  int info = K->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity+maxConnect*i);
378  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
379  "ModeLaplace2DQ1::makeMass(): InsertGlobalValues() returned error code " << info);
380  }
381 
382  // Define the elementary matrix
383  double hx = Lx/nX;
384  double hy = Ly/nY;
385 
386  double *kel = new double[dofEle*dofEle];
387  kel[0] = (hx/hy + hy/hx)/3.0; kel[1] = (hx/hy - 2.0*hy/hx)/6.0;
388  kel[2] = -(hx/hy + hy/hx)/6.0; kel[3] = (hy/hx - 2.0*hx/hy)/6.0;
389  kel[ 4] = kel[1]; kel[ 5] = kel[0]; kel[ 6] = kel[3]; kel[ 7] = kel[2];
390  kel[ 8] = kel[2]; kel[ 9] = kel[3]; kel[10] = kel[0]; kel[11] = kel[1];
391  kel[12] = kel[3]; kel[13] = kel[2]; kel[14] = kel[1]; kel[15] = kel[0];
392 
393  // Assemble the matrix
394  int *indices = new int[dofEle];
395  int numEntries;
396  int j;
397  for (i=0; i<numEle; ++i) {
398  for (j=0; j<dofEle; ++j) {
399  if (elemTopo[dofEle*i + j] == -1)
400  continue;
401  if (Map->LID(elemTopo[dofEle*i+j]) == -1)
402  continue;
403  numEntries = 0;
404  int k;
405  for (k=0; k<dofEle; ++k) {
406  if (elemTopo[dofEle*i+k] == -1)
407  continue;
408  indices[numEntries] = elemTopo[dofEle*i+k];
409  values[numEntries] = kel[dofEle*j + k];
410  numEntries += 1;
411  }
412  int info = K->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
413  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
414  "ModeLaplace2DQ1::makeStiffness(): SumIntoGlobalValues() returned error code " << info);
415  }
416  }
417 
418  delete[] kel;
419  delete[] values;
420  delete[] indices;
421 
422  int info = K->FillComplete();
423  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
424  "ModeLaplace2DQ1::makeStiffness(): FillComplete() returned error code " << info);
425  info = K->OptimizeStorage();
426  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
427  "ModeLaplace2DQ1::makeStiffness(): OptimizeStorage() returned error code " << info);
428 
429 }
430 
431 
432 void ModeLaplace2DQ1::makeMass(int *elemTopo, int numEle, int *connectivity,
433  int *numNz) {
434 
435  // Create Epetra_Matrix for mass
436  M = new Epetra_CrsMatrix(Copy, *Map, numNz);
437 
438  int i;
439  int localSize = Map->NumMyElements();
440 
441  double *values = new double[maxConnect];
442  for (i=0; i<maxConnect; ++i)
443  values[i] = 0.0;
444  for (i=0; i<localSize; ++i) {
445  int info = M->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity + maxConnect*i);
446  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
447  "ModeLaplace2DQ1::makeMass(): InsertGlobalValues() returned error code " << info);
448  }
449 
450  // Define the elementary matrix
451  double hx = Lx/nX;
452  double hy = Ly/nY;
453 
454  double *mel = new double[dofEle*dofEle];
455  mel[0] = hx*hy/9.0; mel[1] = hx*hy/18.0; mel[2] = hx*hy/36.0; mel[3] = hx*hy/18.0;
456  mel[ 4] = mel[1]; mel[ 5] = mel[0]; mel[ 6] = mel[3]; mel[ 7] = mel[2];
457  mel[ 8] = mel[2]; mel[ 9] = mel[3]; mel[10] = mel[0]; mel[11] = mel[1];
458  mel[12] = mel[3]; mel[13] = mel[2]; mel[14] = mel[1]; mel[15] = mel[0];
459 
460  // Assemble the matrix
461  int *indices = new int[dofEle];
462  int numEntries;
463  int j;
464  for (i=0; i<numEle; ++i) {
465  for (j=0; j<dofEle; ++j) {
466  if (elemTopo[dofEle*i + j] == -1)
467  continue;
468  if (Map->LID(elemTopo[dofEle*i+j]) == -1)
469  continue;
470  numEntries = 0;
471  int k;
472  for (k=0; k<dofEle; ++k) {
473  if (elemTopo[dofEle*i+k] == -1)
474  continue;
475  indices[numEntries] = elemTopo[dofEle*i+k];
476  values[numEntries] = mel[dofEle*j + k];
477  numEntries += 1;
478  }
479  int info = M->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
480  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
481  "ModeLaplace2DQ1::makeMass(): SumIntoGlobalValues() returned error code " << info);
482  }
483  }
484 
485  delete[] mel;
486  delete[] values;
487  delete[] indices;
488 
489  int info = M->FillComplete();
490  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
491  "ModeLaplace2DQ1::makeMass(): FillComplete() returned error code " << info);
492  info = M->OptimizeStorage();
493  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
494  "ModeLaplace2DQ1::makeMass(): OptimizeStorage() returned error code " << info);
495 
496 }
497 
498 
499 double ModeLaplace2DQ1::getFirstMassEigenValue() const {
500 
501  return Lx/(3.0*nX)*(2.0-cos(M_PI/nX))*Ly/(3.0*nY)*(2.0-cos(M_PI/nY));
502 
503 }
504 
505 
506 int ModeLaplace2DQ1::eigenCheck(const Epetra_MultiVector &Q, double *lambda,
507  double *normWeight) const {
508 
509  int info = 0;
510  int qc = Q.NumVectors();
511  int myPid = MyComm.MyPID();
512 
513  cout.precision(2);
514  cout.setf(ios::scientific, ios::floatfield);
515 
516  // Check orthonormality of eigenvectors
517  double tmp = myVerify.errorOrthonormality(&Q, M);
518  if (myPid == 0)
519  cout << " Maximum coefficient in matrix Q^T M Q - I = " << tmp << endl;
520 
521  // Print out norm of residuals
522  myVerify.errorEigenResiduals(Q, lambda, K, M, normWeight);
523 
524  // Check the eigenvalues
525  int numX = (int) ceil(sqrt(Lx*Lx*lambda[qc-1]/M_PI/M_PI));
526  numX = (numX > nX) ? nX : numX;
527  int numY = (int) ceil(sqrt(Ly*Ly*lambda[qc-1]/M_PI/M_PI));
528  numY = (numY > nY) ? nY : numY;
529  int newSize = (numX-1)*(numY-1);
530  double *discrete = new (nothrow) double[2*newSize];
531  if (discrete == 0) {
532  return -1;
533  }
534  double *continuous = discrete + newSize;
535 
536  double hx = Lx/nX;
537  double hy = Ly/nY;
538 
539  int i, j;
540  for (j = 1; j < numY; ++j) {
541  for (i = 1; i < numX; ++i) {
542  int pos = i-1 + (j-1)*(numX-1);
543  continuous[pos] = M_PI*M_PI*(i*i/(Lx*Lx) + j*j/(Ly*Ly));
544  discrete[pos] = 6.0*(1.0-cos(i*(M_PI/Lx)*hx))/(2.0+cos(i*(M_PI/Lx)*hx))/hx/hx;
545  discrete[pos] += 6.0*(1.0-cos(j*(M_PI/Ly)*hy))/(2.0+cos(j*(M_PI/Ly)*hy))/hy/hy;
546  }
547  }
548 
549  // Sort the eigenvalues in ascending order
550  mySort.sortScalars(newSize, continuous);
551 
552  int *used = new (nothrow) int[newSize];
553  if (used == 0) {
554  delete[] discrete;
555  return -1;
556  }
557 
558  mySort.sortScalars(newSize, discrete, used);
559 
560  int *index = new (nothrow) int[newSize];
561  if (index == 0) {
562  delete[] discrete;
563  delete[] used;
564  return -1;
565  }
566 
567  for (i=0; i<newSize; ++i) {
568  index[used[i]] = i;
569  }
570  delete[] used;
571 
572  int nMax = myVerify.errorLambda(continuous, discrete, newSize, lambda, qc);
573 
574  // Define the exact discrete eigenvectors
575  int localSize = Map->NumMyElements();
576  double *vQ = new (nothrow) double[(nMax+1)*localSize + nMax];
577  if (vQ == 0) {
578  delete[] discrete;
579  delete[] index;
580  info = -1;
581  return info;
582  }
583 
584  double *normL2 = vQ + (nMax+1)*localSize;
585  Epetra_MultiVector Qex(View, *Map, vQ, localSize, nMax);
586 
587  if ((myPid == 0) && (nMax > 0)) {
588  cout << endl;
589  cout << " --- Relative discretization errors for exact eigenvectors ---" << endl;
590  cout << endl;
591  cout << " Cont. Values Disc. Values Error H^1 norm L^2 norm\n";
592  }
593 
594  for (j=1; j < numY; ++j) {
595  for (i=1; i < numX; ++i) {
596  int pos = i-1 + (j-1)*(numX-1);
597  if (index[pos] < nMax) {
598  double coeff = (2.0 + cos(i*M_PI/Lx*hx))*Lx/6.0;
599  coeff *= (2.0 + cos(j*M_PI/Ly*hy))*Ly/6.0;
600  coeff = 1.0/sqrt(coeff);
601  int ii;
602  for (ii=0; ii<localSize; ++ii) {
603  Qex.ReplaceMyValue(ii, index[pos], coeff*sin(i*(M_PI/Lx)*x[ii])
604  *sin(j*(M_PI/Ly)*y[ii]) );
605  }
606  // Compute the L2 norm
607  Epetra_MultiVector shapeInt(View, *Map, vQ + nMax*localSize, localSize, 1);
608  Epetra_MultiVector Qi(View, Qex, index[pos], 1);
609  for (ii=0; ii<localSize; ++ii) {
610  double iX = 4.0*sqrt(2.0/Lx)*sin(i*(M_PI/Lx)*x[ii])/hx*
611  pow(sin(i*(M_PI/Lx)*0.5*hx)/(i*M_PI/Lx), 2.0);
612  double iY = 4.0*sqrt(2.0/Ly)*sin(j*(M_PI/Ly)*y[ii])/hy*
613  pow(sin(j*(M_PI/Ly)*0.5*hy)/(j*M_PI/Ly), 2.0);
614  shapeInt.ReplaceMyValue(ii, 0, iX*iY);
615  }
616  normL2[index[pos]] = 0.0;
617  Qi.Dot(shapeInt, normL2 + index[pos]);
618  } // if index[pos] < nMax)
619  } // for (i=1; i < numX; ++i)
620  } // for (j=1; j < numY; ++j)
621 
622  if (myPid == 0) {
623  for (i = 0; i < nMax; ++i) {
624  double normH1 = continuous[i]*(1.0 - 2.0*normL2[i]) + discrete[i];
625  normL2[i] = 2.0 - 2.0*normL2[i];
626  normH1+= normL2[i];
627  // Print out the result
628  if (myPid == 0) {
629  cout << " ";
630  cout.width(4);
631  cout << i+1 << ". ";
632  cout.setf(ios::scientific, ios::floatfield);
633  cout.precision(8);
634  cout << continuous[i] << " " << discrete[i] << " ";
635  cout.precision(3);
636  cout << fabs(discrete[i] - continuous[i])/continuous[i] << " ";
637  cout << sqrt(fabs(normH1)/(continuous[i]+1.0)) << " ";
638  cout << sqrt(fabs(normL2[i])) << endl;
639  }
640  } // for (i = 0; i < nMax; ++i)
641  } // if (myPid == 0)
642 
643  delete[] discrete;
644  delete[] index;
645 
646  // Check the angles between exact discrete eigenvectors and computed
647 
648  myVerify.errorSubspaces(Q, Qex, M);
649 
650  delete[] vQ;
651 
652  return info;
653 
654 }
655 
656 
657 void ModeLaplace2DQ1::memoryInfo() const {
658 
659  int myPid = MyComm.MyPID();
660 
661  Epetra_RowMatrix *Mat = dynamic_cast<Epetra_RowMatrix *>(M);
662  if ((myPid == 0) && (Mat)) {
663  cout << " Total number of nonzero entries in mass matrix = ";
664  cout.width(15);
665  cout << Mat->NumGlobalNonzeros() << endl;
666  double memSize = Mat->NumGlobalNonzeros()*(sizeof(double) + sizeof(int));
667  memSize += 2*Mat->NumGlobalRows()*sizeof(int);
668  cout << " Memory requested for mass matrix per processor = (EST) ";
669  cout.precision(2);
670  cout.width(6);
671  cout.setf(ios::fixed, ios::floatfield);
672  cout << memSize/1024.0/1024.0/MyComm.NumProc() << " MB " << endl;
673  cout << endl;
674  }
675 
676  Mat = dynamic_cast<Epetra_RowMatrix *>(K);
677  if ((myPid == 0) && (Mat)) {
678  cout << " Total number of nonzero entries in stiffness matrix = ";
679  cout.width(15);
680  cout << Mat->NumGlobalNonzeros() << endl;
681  double memSize = Mat->NumGlobalNonzeros()*(sizeof(double) + sizeof(int));
682  memSize += 2*Mat->NumGlobalRows()*sizeof(int);
683  cout << " Memory requested for stiffness matrix per processor = (EST) ";
684  cout.precision(2);
685  cout.width(6);
686  cout.setf(ios::fixed, ios::floatfield);
687  cout << memSize/1024.0/1024.0/MyComm.NumProc() << " MB " << endl;
688  cout << endl;
689  }
690 
691 }
692 
693 
694 void ModeLaplace2DQ1::problemInfo() const {
695 
696  int myPid = MyComm.MyPID();
697 
698  if (myPid == 0) {
699  cout.precision(2);
700  cout.setf(ios::fixed, ios::floatfield);
701  cout << " --- Problem definition ---\n\n";
702  cout << " >> Laplace equation in 2D with homogeneous Dirichlet condition\n";
703  cout << " >> Domain = [0, " << Lx << "] x [0, " << Ly << "]\n";
704  cout << " >> Orthogonal mesh uniform per direction with Q1 elements\n";
705  cout << endl;
706  cout << " Global size = " << Map->NumGlobalElements() << endl;
707  cout << endl;
708  cout << " Number of elements in [0, " << Lx << "] (X-direction): " << nX << endl;
709  cout << " Number of elements in [0, " << Ly << "] (Y-direction): " << nY << endl;
710  cout << endl;
711  cout << " Number of interior nodes in the X-direction: " << nX-1 << endl;
712  cout << " Number of interior nodes in the Y-direction: " << nY-1 << endl;
713  cout << endl;
714  }
715 
716 }
717 
718 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual int NumGlobalNonzeros() const =0
virtual int NumGlobalRows() const =0