35 #include "ModeLaplace2DQ1.h"
36 #include "Teuchos_Assert.hpp"
39 const int ModeLaplace2DQ1::dofEle = 4;
40 const int ModeLaplace2DQ1::maxConnect = 9;
42 const double ModeLaplace2DQ1::M_PI = 3.14159265358979323846;
46 ModeLaplace2DQ1::ModeLaplace2DQ1(
const Epetra_Comm &_Comm,
double _Lx,
int _nX,
67 ModeLaplace2DQ1::~ModeLaplace2DQ1() {
92 void ModeLaplace2DQ1::preProcess() {
98 bool *isTouched =
new bool[nX*nY];
100 for (j = 0; j < nY; ++j)
102 isTouched[i + j*nX] =
false;
104 int numEle = countElements(isTouched);
107 int *elemTopo =
new int[dofEle*numEle];
108 makeMyElementsTopology(elemTopo, isTouched);
113 int localSize = Map->NumMyElements();
114 int *numNz =
new int[localSize];
115 int *connectivity =
new int[localSize*maxConnect];
116 makeMyConnectivity(elemTopo, numEle, connectivity, numNz);
119 makeStiffness(elemTopo, numEle, connectivity, numNz);
122 makeMass(elemTopo, numEle, connectivity, numNz);
127 delete[] connectivity;
133 x =
new double[localSize];
134 y =
new double[localSize];
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;
149 void ModeLaplace2DQ1::makeMap() {
151 int numProc = MyComm.NumProc();
152 int globalSize = (nX - 1)*(nY - 1);
153 assert(globalSize > numProc);
157 int *start =
new int[globalSize+1];
158 memset(start, 0, (globalSize+1)*
sizeof(
int));
161 for (j=0; j<nY-1; ++j) {
162 for (i=0; i<nX-1; ++i) {
163 int node = i + j*(nX-1);
165 connect *= ((i == 0) || (i == nX-2)) ? 2 : 3;
166 connect *= ((j == 0) || (j == nY-2)) ? 2 : 3;
168 start[node+1] = connect - 1;
172 for (i = 0; i < globalSize; ++i)
173 start[i+1] += start[i];
175 int *adjacency =
new int[start[globalSize]];
176 memset(adjacency, 0, start[globalSize]*
sizeof(
int));
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)
189 for (
int jD = 0; jD < dofEle; ++jD) {
190 int neighbor = elemTopo[jD];
192 if ((neighbor == -1) || (iD == jD))
195 for (
int l = start[elemTopo[iD]]; l < start[elemTopo[iD]+1]; ++l) {
197 if (adjacency[l] == neighbor + 1)
199 if (adjacency[l] == 0) {
202 adjacency[l] = elemTopo[jD] + 1;
216 short int *partition =
new short int[globalSize];
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);
222 int myPid = MyComm.MyPID();
223 for (i = 0; i < globalSize; ++i) {
224 if (partition[i] == myPid)
227 int *myRows =
new int[localSize];
229 for (i = 0; i < globalSize; ++i) {
230 if (partition[i] == myPid) {
231 myRows[localSize] = i;
238 Map =
new Epetra_Map(globalSize, localSize, myRows, 0, MyComm);
248 int ModeLaplace2DQ1::countElements(
bool *isTouched) {
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);
261 node = ((i==0) || (j==0)) ? -1 : bottomLeft;
262 if ((node > -1) && (Map->LID(node) > -1)) {
263 isTouched[i+j*nX] =
true;
267 node = ((i==nX-1) || (j==0)) ? -1 : bottomLeft + 1;
268 if ((node > -1) && (Map->LID(node) > -1)) {
269 isTouched[i+j*nX] =
true;
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;
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;
293 void ModeLaplace2DQ1::makeMyElementsTopology(
int *elemTopo,
bool *isTouched) {
301 for (j=0; j<nY; ++j) {
302 for (i=0; i<nX; ++i) {
303 if (isTouched[i + j*nX] ==
false)
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;
317 void ModeLaplace2DQ1::makeMyConnectivity(
int *elemTopo,
int numEle,
int *connectivity,
324 int localSize = Map->NumMyElements();
326 for (i=0; i<localSize; ++i) {
328 for (j=0; j<maxConnect; ++j) {
329 connectivity[i*maxConnect + j] = -1;
333 for (i=0; i<numEle; ++i) {
334 for (j=0; j<dofEle; ++j) {
335 if (elemTopo[dofEle*i+j] == -1)
337 int node = Map->LID(elemTopo[dofEle*i+j]);
340 for (k=0; k<dofEle; ++k) {
341 int neighbor = elemTopo[dofEle*i+k];
346 for (l=0; l<maxConnect; ++l) {
347 if (neighbor == connectivity[node*maxConnect + l])
349 if (connectivity[node*maxConnect + l] == -1) {
350 connectivity[node*maxConnect + l] = neighbor;
363 void ModeLaplace2DQ1::makeStiffness(
int *elemTopo,
int numEle,
int *connectivity,
370 int localSize = Map->NumMyElements();
372 double *values =
new double[maxConnect];
373 for (i=0; i<maxConnect; ++i)
376 for (i=0; i<localSize; ++i) {
377 int info = K->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity+maxConnect*i);
379 "ModeLaplace2DQ1::makeMass(): InsertGlobalValues() returned error code " << info);
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];
394 int *indices =
new int[dofEle];
397 for (i=0; i<numEle; ++i) {
398 for (j=0; j<dofEle; ++j) {
399 if (elemTopo[dofEle*i + j] == -1)
401 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
405 for (k=0; k<dofEle; ++k) {
406 if (elemTopo[dofEle*i+k] == -1)
408 indices[numEntries] = elemTopo[dofEle*i+k];
409 values[numEntries] = kel[dofEle*j + k];
412 int info = K->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
414 "ModeLaplace2DQ1::makeStiffness(): SumIntoGlobalValues() returned error code " << info);
422 int info = K->FillComplete();
424 "ModeLaplace2DQ1::makeStiffness(): FillComplete() returned error code " << info);
425 info = K->OptimizeStorage();
427 "ModeLaplace2DQ1::makeStiffness(): OptimizeStorage() returned error code " << info);
432 void ModeLaplace2DQ1::makeMass(
int *elemTopo,
int numEle,
int *connectivity,
439 int localSize = Map->NumMyElements();
441 double *values =
new double[maxConnect];
442 for (i=0; i<maxConnect; ++i)
444 for (i=0; i<localSize; ++i) {
445 int info = M->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity + maxConnect*i);
447 "ModeLaplace2DQ1::makeMass(): InsertGlobalValues() returned error code " << info);
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];
461 int *indices =
new int[dofEle];
464 for (i=0; i<numEle; ++i) {
465 for (j=0; j<dofEle; ++j) {
466 if (elemTopo[dofEle*i + j] == -1)
468 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
472 for (k=0; k<dofEle; ++k) {
473 if (elemTopo[dofEle*i+k] == -1)
475 indices[numEntries] = elemTopo[dofEle*i+k];
476 values[numEntries] = mel[dofEle*j + k];
479 int info = M->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
481 "ModeLaplace2DQ1::makeMass(): SumIntoGlobalValues() returned error code " << info);
489 int info = M->FillComplete();
491 "ModeLaplace2DQ1::makeMass(): FillComplete() returned error code " << info);
492 info = M->OptimizeStorage();
494 "ModeLaplace2DQ1::makeMass(): OptimizeStorage() returned error code " << info);
499 double ModeLaplace2DQ1::getFirstMassEigenValue()
const {
501 return Lx/(3.0*nX)*(2.0-cos(M_PI/nX))*Ly/(3.0*nY)*(2.0-cos(M_PI/nY));
507 double *normWeight)
const {
510 int qc = Q.NumVectors();
511 int myPid = MyComm.MyPID();
514 cout.setf(ios::scientific, ios::floatfield);
517 double tmp = myVerify.errorOrthonormality(&Q, M);
519 cout <<
" Maximum coefficient in matrix Q^T M Q - I = " << tmp << endl;
522 myVerify.errorEigenResiduals(Q, lambda, K, M, normWeight);
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];
534 double *continuous = discrete + newSize;
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;
550 mySort.sortScalars(newSize, continuous);
552 int *used =
new (nothrow)
int[newSize];
558 mySort.sortScalars(newSize, discrete, used);
560 int *index =
new (nothrow)
int[newSize];
567 for (i=0; i<newSize; ++i) {
572 int nMax = myVerify.errorLambda(continuous, discrete, newSize, lambda, qc);
575 int localSize = Map->NumMyElements();
576 double *vQ =
new (nothrow)
double[(nMax+1)*localSize + nMax];
584 double *normL2 = vQ + (nMax+1)*localSize;
587 if ((myPid == 0) && (nMax > 0)) {
589 cout <<
" --- Relative discretization errors for exact eigenvectors ---" << endl;
591 cout <<
" Cont. Values Disc. Values Error H^1 norm L^2 norm\n";
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);
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]) );
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);
616 normL2[index[pos]] = 0.0;
617 Qi.Dot(shapeInt, normL2 + index[pos]);
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];
632 cout.setf(ios::scientific, ios::floatfield);
634 cout << continuous[i] <<
" " << discrete[i] <<
" ";
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;
648 myVerify.errorSubspaces(Q, Qex, M);
657 void ModeLaplace2DQ1::memoryInfo()
const {
659 int myPid = MyComm.MyPID();
662 if ((myPid == 0) && (Mat)) {
663 cout <<
" Total number of nonzero entries in mass matrix = ";
668 cout <<
" Memory requested for mass matrix per processor = (EST) ";
671 cout.setf(ios::fixed, ios::floatfield);
672 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
677 if ((myPid == 0) && (Mat)) {
678 cout <<
" Total number of nonzero entries in stiffness matrix = ";
683 cout <<
" Memory requested for stiffness matrix per processor = (EST) ";
686 cout.setf(ios::fixed, ios::floatfield);
687 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
694 void ModeLaplace2DQ1::problemInfo()
const {
696 int myPid = MyComm.MyPID();
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";
706 cout <<
" Global size = " << Map->NumGlobalElements() << 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;
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;
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual int NumGlobalNonzeros() const =0
virtual int NumGlobalRows() const =0