35 #include "ModeLaplace1DQ2.h"
36 #include "Teuchos_Assert.hpp"
39 const int ModeLaplace1DQ2::dofEle = 3;
40 const int ModeLaplace1DQ2::maxConnect = 5;
42 const double ModeLaplace1DQ2::M_PI = 3.14159265358979323846;
46 ModeLaplace1DQ2::ModeLaplace1DQ2(
const Epetra_Comm &_Comm,
double _Lx,
int _nX)
63 ModeLaplace1DQ2::~ModeLaplace1DQ2() {
84 void ModeLaplace1DQ2::preProcess() {
90 bool *isTouched =
new bool[nX];
95 int numEle = countElements(isTouched);
98 int *elemTopo =
new int[dofEle*numEle];
99 makeMyElementsTopology(elemTopo, isTouched);
104 int localSize = Map->NumMyElements();
105 int *numNz =
new int[localSize];
106 int *connectivity =
new int[localSize*maxConnect];
107 makeMyConnectivity(elemTopo, numEle, connectivity, numNz);
110 makeStiffness(elemTopo, numEle, connectivity, numNz);
113 makeMass(elemTopo, numEle, connectivity, numNz);
118 delete[] connectivity;
123 x =
new double[localSize];
125 for (i=0; i<2*nX-1; ++i) {
127 if (Map->LID(node) > -1) {
128 x[Map->LID(node)] = (i+1)*hx*0.5;
135 void ModeLaplace1DQ2::makeMap() {
137 int globalSize = (2*nX - 1);
138 assert(globalSize > MyComm.NumProc());
146 int ModeLaplace1DQ2::countElements(
bool *isTouched) {
154 for (i=0; i<nX; ++i) {
155 isTouched[i] =
false;
157 node = (i==0) ? -1 : 2*i-1;
158 if ((node > -1) && (Map->LID(node) > -1)) {
163 node = (i==nX-1) ? -1 : 2*i+1;
164 if ((node > -1) && (Map->LID(node) > -1)) {
170 if ((node > -1) && (Map->LID(node) > -1)) {
182 void ModeLaplace1DQ2::makeMyElementsTopology(
int *elemTopo,
bool *isTouched) {
190 for (i=0; i<nX; ++i) {
191 if (isTouched[i] ==
false)
193 elemTopo[dofEle*numEle] = (i==0) ? -1 : 2*i-1;
194 elemTopo[dofEle*numEle+1] = (i==nX-1) ? -1 : 2*i+1;
195 elemTopo[dofEle*numEle+2] = 2*i;
202 void ModeLaplace1DQ2::makeMyConnectivity(
int *elemTopo,
int numEle,
int *connectivity,
209 int localSize = Map->NumMyElements();
211 for (i=0; i<localSize; ++i) {
213 for (j=0; j<maxConnect; ++j) {
214 connectivity[i*maxConnect + j] = -1;
218 for (i=0; i<numEle; ++i) {
219 for (j=0; j<dofEle; ++j) {
220 if (elemTopo[dofEle*i+j] == -1)
222 int node = Map->LID(elemTopo[dofEle*i+j]);
225 for (k=0; k<dofEle; ++k) {
226 int neighbor = elemTopo[dofEle*i+k];
231 for (l=0; l<maxConnect; ++l) {
232 if (neighbor == connectivity[node*maxConnect + l])
234 if (connectivity[node*maxConnect + l] == -1) {
235 connectivity[node*maxConnect + l] = neighbor;
248 void ModeLaplace1DQ2::makeStiffness(
int *elemTopo,
int numEle,
int *connectivity,
255 int localSize = Map->NumMyElements();
257 double *values =
new double[maxConnect];
258 for (i=0; i<maxConnect; ++i)
261 for (i=0; i<localSize; ++i) {
262 int info = K->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity+maxConnect*i);
264 "ModeLaplace1DQ2::makeStiffness(): InsertGlobalValues() returned error code " << info);
268 double *kel =
new double[dofEle*dofEle];
269 makeElementaryStiffness(kel);
272 int *indices =
new int[dofEle];
275 for (i=0; i<numEle; ++i) {
276 for (j=0; j<dofEle; ++j) {
277 if (elemTopo[dofEle*i + j] == -1)
279 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
283 for (k=0; k<dofEle; ++k) {
284 if (elemTopo[dofEle*i+k] == -1)
286 indices[numEntries] = elemTopo[dofEle*i+k];
287 values[numEntries] = kel[dofEle*j + k];
290 int info = K->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
292 "ModeLaplace1DQ2::makeStiffness(): SumIntoGlobalValues() returned error code " << info);
300 int info = K->FillComplete();
302 "ModeLaplace1DQ2::makeStiffness(): FillComplete() returned error code " << info);
303 info = K->OptimizeStorage();
305 "ModeLaplace1DQ2::makeStiffness(): OptimizeStorage() returned error code " << info);
310 void ModeLaplace1DQ2::makeElementaryStiffness(
double *kel)
const {
314 kel[0] = 7.0/(3.0*hx); kel[1] = 1.0/(3.0*hx); kel[2] = - 8.0/(3.0*hx);
315 kel[3] = 1.0/(3.0*hx); kel[4] = 7.0/(3.0*hx); kel[5] = - 8.0/(3.0*hx);
316 kel[6] = - 8.0/(3.0*hx); kel[7] = - 8.0/(3.0*hx); kel[8] = 16.0/(3.0*hx);
321 void ModeLaplace1DQ2::makeMass(
int *elemTopo,
int numEle,
int *connectivity,
328 int localSize = Map->NumMyElements();
330 double *values =
new double[maxConnect];
331 for (i=0; i<maxConnect; ++i)
333 for (i=0; i<localSize; ++i) {
334 int info = M->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity + maxConnect*i);
336 "ModeLaplace1DQ2::makeMass(): InsertGlobalValues() returned error code " << info);
340 double *mel =
new double[dofEle*dofEle];
341 makeElementaryMass(mel);
344 int *indices =
new int[dofEle];
347 for (i=0; i<numEle; ++i) {
348 for (j=0; j<dofEle; ++j) {
349 if (elemTopo[dofEle*i + j] == -1)
351 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
355 for (k=0; k<dofEle; ++k) {
356 if (elemTopo[dofEle*i+k] == -1)
358 indices[numEntries] = elemTopo[dofEle*i+k];
359 values[numEntries] = mel[dofEle*j + k];
362 int info = M->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
364 "ModeLaplace1DQ2::makeMass(): SumIntoGlobalValues() returned error code " << info);
372 int info = M->FillComplete();
374 "ModeLaplace1DQ2::makeMass(): FillComplete() returned error code " << info);
375 info = M->OptimizeStorage();
377 "ModeLaplace1DQ2::makeMass(): OptimizeStorage() returned error code " << info);
381 void ModeLaplace1DQ2::makeElementaryMass(
double *mel)
const {
385 mel[0] = 2.0*hx/15.0; mel[1] = -hx/30.0; mel[2] = hx/15.0;
386 mel[3] = -hx/30.0; mel[4] = 2.0*hx/15.0; mel[5] = hx/15.0;
387 mel[6] = hx/15.0; mel[7] = hx/15.0; mel[8] = 8.0*hx/15.0;
392 double ModeLaplace1DQ2::getFirstMassEigenValue()
const {
397 double cosi = cos(M_PI*hx/2/Lx);
399 double b = 4.0 + cos(M_PI*hx/Lx);
400 double c = -2.0*cosi;
401 double delta = sqrt(b*b - 4*a*c);
402 double alphax = (-b - delta)*0.5/a;
404 double discrete = hx/15.0*(8.0+2*alphax*cosi);
412 double *normWeight)
const {
415 int qc = Q.NumVectors();
416 int myPid = MyComm.MyPID();
419 cout.setf(ios::scientific, ios::floatfield);
422 double tmp = myVerify.errorOrthonormality(&Q, M);
424 cout <<
" Maximum coefficient in matrix Q^T M Q - I = " << tmp << endl;
427 myVerify.errorEigenResiduals(Q, lambda, K, M, normWeight);
430 int numX = (int) ceil(sqrt(Lx*Lx*lambda[qc-1]/M_PI/M_PI));
431 numX = (numX > 2*nX) ? 2*nX : numX;
432 int newSize = (numX-1);
433 double *discrete =
new (nothrow)
double[2*newSize];
437 double *continuous = discrete + newSize;
442 for (i = 1; i < numX; ++i) {
443 continuous[i-1] = (M_PI/Lx)*(M_PI/Lx)*i*i;
445 double cosi = cos(i*M_PI*hx/2.0/Lx);
446 double a = cosi*(92.0 - 12.0*cos(i*M_PI*hx/Lx));
447 double b = 48.0 + 32.0*cos(i*M_PI*hx/Lx);
448 double c = -160.0*cosi;
449 double delta = sqrt(b*b - 4*a*c);
450 double alphaX = (-b - delta)*0.5/a;
451 alphaX = (alphaX < 0.0) ? (-b + delta)*0.5/a : alphaX;
453 discrete[i-1] = 240.0*(1.0 - alphaX*cosi)/( (8.0 + 2*alphaX*cosi)*(3.0*hx*hx) );
457 mySort.sortScalars(newSize, continuous);
459 int *used =
new (nothrow)
int[newSize];
465 mySort.sortScalars(newSize, discrete, used);
467 int *index =
new (nothrow)
int[newSize];
474 for (i=0; i<newSize; ++i) {
479 int nMax = myVerify.errorLambda(continuous, discrete, newSize, lambda, qc);
482 int localSize = Map->NumMyElements();
483 double *vQ =
new (nothrow)
double[(nMax+1)*localSize + nMax];
491 double *normL2 = vQ + (nMax+1)*localSize;
494 if ((myPid == 0) && (nMax > 0)) {
496 cout <<
" --- Relative discretization errors for exact eigenvectors ---" << endl;
498 cout <<
" Cont. Values Disc. Values Error H^1 norm L^2 norm\n";
501 for (i=1; i < numX; ++i) {
502 if (index[i-1] < nMax) {
504 double cosi = cos(i*M_PI*hx/2/Lx);
505 double a = cosi*(92.0 - 12.0*cos(i*M_PI*hx/Lx));
506 double b = 48.0 + 32.0*cos(i*M_PI*hx/Lx);
507 double c = -160.0*cosi;
508 double delta = sqrt(b*b - 4*a*c);
509 double alphaX = (-b - delta)*0.5/a;
510 alphaX = (alphaX < 0.0) ? (-b + delta)*0.5/a : alphaX;
512 for (ii=0; ii<localSize; ++ii) {
513 if (fabs(x[ii] - floor(x[ii]/hx+0.5)*hx) < 0.25*hx) {
514 Qex.ReplaceMyValue(ii, index[i-1], alphaX*sin(i*(M_PI/Lx)*x[ii]));
517 Qex.ReplaceMyValue(ii, index[i-1], sin(i*(M_PI/Lx)*x[ii]));
525 Qi.Dot(MQex, &mnorm);
526 Qi.Scale(1.0/sqrt(mnorm));
529 for (ii=0; ii<localSize; ++ii) {
531 if (fabs(x[ii] - floor(x[ii]/hx+0.5)*hx) < 0.25*hx)
532 iX = 2.0*sin(i*(M_PI/Lx)*x[ii])/(hx*hx*i*(M_PI/Lx)*i*(M_PI/Lx)*i*(M_PI/Lx))*
533 sqrt(2.0/Lx)*( 3*hx*i*(M_PI/Lx) - 4*sin(i*(M_PI/Lx)*hx) +
534 cos(i*(M_PI/Lx)*hx)*hx*i*(M_PI/Lx) );
536 iX = 8.0*sin(i*(M_PI/Lx)*x[ii])/(hx*hx*i*(M_PI/Lx)*i*(M_PI/Lx)*i*(M_PI/Lx))*
537 sqrt(2.0/Lx)*( 2*sin(i*(M_PI/Lx)*0.5*hx) -
538 cos(i*(M_PI/Lx)*0.5*hx)*hx*i*(M_PI/Lx));
539 shapeInt.ReplaceMyValue(ii, 0, iX);
541 Qi.Dot(shapeInt, normL2+index[i-1]);
546 for (i = 0; i < nMax; ++i) {
547 double normH1 = continuous[i]*(1.0 - 2.0*normL2[i]) + discrete[i];
548 normL2[i] = 2.0 - 2.0*normL2[i];
555 cout.setf(ios::scientific, ios::floatfield);
557 cout << continuous[i] <<
" " << discrete[i] <<
" ";
559 cout << fabs(discrete[i] - continuous[i])/continuous[i] <<
" ";
560 cout << sqrt(fabs(normH1)/(continuous[i]+1.0)) <<
" ";
561 cout << sqrt(fabs(normL2[i])) << endl;
571 myVerify.errorSubspaces(Q, Qex, M);
580 void ModeLaplace1DQ2::memoryInfo()
const {
582 int myPid = MyComm.MyPID();
585 if ((myPid == 0) && (Mat)) {
586 cout <<
" Total number of nonzero entries in mass matrix = ";
591 cout <<
" Memory requested for mass matrix per processor = (EST) ";
594 cout.setf(ios::fixed, ios::floatfield);
595 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
600 if ((myPid == 0) && (Mat)) {
601 cout <<
" Total number of nonzero entries in stiffness matrix = ";
606 cout <<
" Memory requested for stiffness matrix per processor = (EST) ";
609 cout.setf(ios::fixed, ios::floatfield);
610 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
617 void ModeLaplace1DQ2::problemInfo()
const {
619 int myPid = MyComm.MyPID();
623 cout.setf(ios::fixed, ios::floatfield);
624 cout <<
" --- Problem definition ---\n\n";
625 cout <<
" >> Laplace equation in 1D with homogeneous Dirichlet condition\n";
626 cout <<
" >> Domain = [0, " << Lx <<
"]\n";
627 cout <<
" >> Orthogonal mesh uniform per direction with Q2 elements (3 nodes)\n";
629 cout <<
" Global size = " << Map->NumGlobalElements() << endl;
631 cout <<
" Number of elements in [0, " << Lx <<
"] (X-direction): " << nX << endl;
633 cout <<
" Number of interior nodes in the X-direction: " << 2*nX-1 << endl;
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual int NumGlobalNonzeros() const =0
virtual int NumGlobalRows() const =0