Anasazi Version of the Day
Loading...
Searching...
No Matches
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
39const int ModeLaplace2DQ1::dofEle = 4;
40const int ModeLaplace2DQ1::maxConnect = 9;
41#ifndef M_PI
42const double ModeLaplace2DQ1::M_PI = 3.14159265358979323846;
43#endif
44
45
46ModeLaplace2DQ1::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
67ModeLaplace2DQ1::~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
92void 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
149void 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
248int 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
293void 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
317void 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
363void 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
432void 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
499double 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
506int 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
657void 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
694void 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