19 #include "ModeLaplace1DQ1.h"
20 #include "Teuchos_Assert.hpp"
23 const int ModeLaplace1DQ1::dofEle = 2;
24 const int ModeLaplace1DQ1::maxConnect = 3;
26 const double ModeLaplace1DQ1::M_PI = 3.14159265358979323846;
30 ModeLaplace1DQ1::ModeLaplace1DQ1(
const Epetra_Comm &_Comm,
double _Lx,
int _nX)
47 ModeLaplace1DQ1::~ModeLaplace1DQ1() {
68 void ModeLaplace1DQ1::preProcess() {
74 bool *isTouched =
new bool[nX];
79 int numEle = countElements(isTouched);
82 int *elemTopo =
new int[dofEle*numEle];
83 makeMyElementsTopology(elemTopo, isTouched);
88 int localSize = Map->NumMyElements();
89 int *numNz =
new int[localSize];
90 int *connectivity =
new int[localSize*maxConnect];
91 makeMyConnectivity(elemTopo, numEle, connectivity, numNz);
94 makeStiffness(elemTopo, numEle, connectivity, numNz);
97 makeMass(elemTopo, numEle, connectivity, numNz);
102 delete[] connectivity;
106 x =
new double[localSize];
108 int globalSize = Map->NumGlobalElements();
109 for (i=0; i<globalSize; ++i) {
110 if (Map->LID(i) > -1) {
111 x[Map->LID(i)] = (i+1)*hx;
118 void ModeLaplace1DQ1::makeMap() {
120 int globalSize = nX - 1;
121 assert(globalSize > MyComm.NumProc());
129 int ModeLaplace1DQ1::countElements(
bool *isTouched) {
137 for (i=0; i<nX; ++i) {
139 node = (i==0) ? -1 : i-1;
140 if ((node > -1) && (Map->LID(node) > -1)) {
145 node = (i==nX-1) ? -1 : i;
146 if ((node > -1) && (Map->LID(node) > -1)) {
158 void ModeLaplace1DQ1::makeMyElementsTopology(
int *elemTopo,
bool *isTouched) {
166 for (i=0; i<nX; ++i) {
167 if (isTouched[i] ==
false)
169 elemTopo[dofEle*numEle] = (i==0) ? -1 : i-1;
170 elemTopo[dofEle*numEle+1] = (i==nX-1) ? -1 : i;
177 void ModeLaplace1DQ1::makeMyConnectivity(
int *elemTopo,
int numEle,
int *connectivity,
184 int localSize = Map->NumMyElements();
186 for (i=0; i<localSize; ++i) {
188 for (j=0; j<maxConnect; ++j) {
189 connectivity[i*maxConnect + j] = -1;
193 for (i=0; i<numEle; ++i) {
194 for (j=0; j<dofEle; ++j) {
195 if (elemTopo[dofEle*i+j] == -1)
197 int node = Map->LID(elemTopo[dofEle*i+j]);
200 for (k=0; k<dofEle; ++k) {
201 int neighbor = elemTopo[dofEle*i+k];
206 for (l=0; l<maxConnect; ++l) {
207 if (neighbor == connectivity[node*maxConnect + l])
209 if (connectivity[node*maxConnect + l] == -1) {
210 connectivity[node*maxConnect + l] = neighbor;
223 void ModeLaplace1DQ1::makeStiffness(
int *elemTopo,
int numEle,
int *connectivity,
230 int localSize = Map->NumMyElements();
232 double *values =
new double[maxConnect];
233 for (i=0; i<maxConnect; ++i)
236 for (i=0; i<localSize; ++i) {
237 int info = K->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity+maxConnect*i);
239 "ModeLaplace1DQ1::makeStiffness(): InsertGlobalValues() returned error code " << info);
244 double *kel =
new double[dofEle*dofEle];
245 kel[0] = 1.0/hx; kel[1] = -1.0/hx;
246 kel[2] = -1.0/hx; kel[3] = 1.0/hx;
249 int *indices =
new int[dofEle];
252 for (i=0; i<numEle; ++i) {
253 for (j=0; j<dofEle; ++j) {
254 if (elemTopo[dofEle*i + j] == -1)
256 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
260 for (k=0; k<dofEle; ++k) {
261 if (elemTopo[dofEle*i+k] == -1)
263 indices[numEntries] = elemTopo[dofEle*i+k];
264 values[numEntries] = kel[dofEle*j + k];
267 int info = K->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
269 "ModeLaplace1DQ1::makeStiffness(): SumIntoGlobalValues() returned error code " << info);
278 info = K->FillComplete();
280 "ModeLaplace1DQ1::makeStiffness(): FillComplete() returned error code " << info);
281 info = K->OptimizeStorage();
283 "ModeLaplace1DQ1::makeStiffness(): OptimizeStorage() returned error code " << info);
287 void ModeLaplace1DQ1::makeMass(
int *elemTopo,
int numEle,
int *connectivity,
294 int localSize = Map->NumMyElements();
296 double *values =
new double[maxConnect];
297 for (i=0; i<maxConnect; ++i)
299 for (i=0; i<localSize; ++i) {
300 int info = M->InsertGlobalValues(Map->GID(i), numNz[i], values, connectivity + maxConnect*i);
302 "ModeLaplace1DQ1::makeMass(): InsertGlobalValues() returned error code " << info);
308 double *mel =
new double[dofEle*dofEle];
309 mel[0] = hx/3.0; mel[1] = hx/6.0;
310 mel[2] = hx/6.0; mel[3] = hx/3.0;
313 int *indices =
new int[dofEle];
316 for (i=0; i<numEle; ++i) {
317 for (j=0; j<dofEle; ++j) {
318 if (elemTopo[dofEle*i + j] == -1)
320 if (Map->LID(elemTopo[dofEle*i+j]) == -1)
324 for (k=0; k<dofEle; ++k) {
325 if (elemTopo[dofEle*i+k] == -1)
327 indices[numEntries] = elemTopo[dofEle*i+k];
328 values[numEntries] = mel[dofEle*j + k];
331 int info = M->SumIntoGlobalValues(elemTopo[dofEle*i+j], numEntries, values, indices);
333 "ModeLaplace1DQ1::makeMass(): SumIntoGlobalValues() returned error code " << info);
341 int info = M->FillComplete();
343 "ModeLaplace1DQ1::makeMass(): FillComplete() returned error code " << info);
344 info = M->OptimizeStorage();
346 "ModeLaplace1DQ1::makeMass(): OptimizeStorage() returned error code " << info);
350 double ModeLaplace1DQ1::getFirstMassEigenValue()
const {
352 return Lx/(3.0*nX)*(2.0-cos(M_PI/nX));
358 double *normWeight)
const {
361 int qc = Q.NumVectors();
362 int myPid = MyComm.MyPID();
365 cout.setf(ios::scientific, ios::floatfield);
368 double tmp = myVerify.errorOrthonormality(&Q, M);
370 cout <<
" Maximum coefficient in matrix Q^T M Q - I = " << tmp << endl;
373 myVerify.errorEigenResiduals(Q, lambda, K, M, normWeight);
376 int numX = (int) ceil(sqrt(Lx*Lx*lambda[qc-1]/M_PI/M_PI));
377 numX = (numX > nX) ? nX : numX;
378 int newSize = (numX-1);
379 double *discrete =
new (nothrow)
double[2*newSize];
383 double *continuous = discrete + newSize;
388 for (i = 1; i < numX; ++i) {
389 continuous[i-1] = (M_PI/Lx)*(M_PI/Lx)*i*i;
390 discrete[i-1] = 6.0*(1.0-cos(i*(M_PI/Lx)*hx))/(2.0+cos(i*(M_PI/Lx)*hx))/hx/hx;
394 mySort.sortScalars(newSize, continuous);
396 int *used =
new (nothrow)
int[newSize];
402 mySort.sortScalars(newSize, discrete, used);
404 int *index =
new (nothrow)
int[newSize];
411 for (i=0; i<newSize; ++i) {
416 int nMax = myVerify.errorLambda(continuous, discrete, newSize, lambda, qc);
419 int localSize = Map->NumMyElements();
420 double *vQ =
new (nothrow)
double[(nMax+1)*localSize];
430 if ((myPid == 0) && (nMax > 0)) {
432 cout <<
" --- Relative discretization errors for exact eigenvectors ---" << endl;
434 cout <<
" Cont. Values Disc. Values Error H^1 norm L^2 norm\n";
437 for (i=1; i < numX; ++i) {
438 if (index[i-1] < nMax) {
440 double coeff = (2.0 + cos(i*M_PI/Lx*hx))*Lx/6.0;
441 coeff = 1.0/sqrt(coeff);
443 for (ii=0; ii<localSize; ++ii) {
444 Qex.ReplaceMyValue(ii, index[i-1], coeff*sin(i*(M_PI/Lx)*x[ii]));
449 for (ii=0; ii<localSize; ++ii) {
450 double iX = 4.0*sqrt(2.0/Lx)*sin(i*(M_PI/Lx)*x[ii])/hx*
451 pow(sin(i*(M_PI/Lx)*0.5*hx)/(i*M_PI/Lx), 2.0);
452 shapeInt.ReplaceMyValue(ii, 0, iX);
455 Qi.Dot(shapeInt, &normL2);
456 double normH1 = continuous[i-1]*(1.0 - 2.0*normL2) + discrete[i-1];
457 normL2 = 2.0 - 2.0*normL2;
463 cout << index[i-1] <<
". ";
464 cout.setf(ios::scientific, ios::floatfield);
466 cout << continuous[i-1] <<
" " << discrete[i-1] <<
" ";
468 cout << fabs(discrete[i-1] - continuous[i-1])/continuous[i-1] <<
" ";
469 cout << sqrt(fabs(normH1)/(continuous[i-1]+1.0)) <<
" ";
470 cout << sqrt(fabs(normL2)) << endl;
480 myVerify.errorSubspaces(Q, Qex, M);
489 void ModeLaplace1DQ1::memoryInfo()
const {
491 int myPid = MyComm.MyPID();
494 if ((myPid == 0) && (Mat)) {
495 cout <<
" Total number of nonzero entries in mass matrix = ";
500 cout <<
" Memory requested for mass matrix per processor = (EST) ";
503 cout.setf(ios::fixed, ios::floatfield);
504 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
509 if ((myPid == 0) && (Mat)) {
510 cout <<
" Total number of nonzero entries in stiffness matrix = ";
515 cout <<
" Memory requested for stiffness matrix per processor = (EST) ";
518 cout.setf(ios::fixed, ios::floatfield);
519 cout << memSize/1024.0/1024.0/MyComm.NumProc() <<
" MB " << endl;
526 void ModeLaplace1DQ1::problemInfo()
const {
528 int myPid = MyComm.MyPID();
532 cout.setf(ios::fixed, ios::floatfield);
533 cout <<
" --- Problem definition ---\n\n";
534 cout <<
" >> Laplace equation in 1D with homogeneous Dirichlet condition\n";
535 cout <<
" >> Domain = [0, " << Lx <<
"]\n";
536 cout <<
" >> Orthogonal mesh uniform per direction with Q1 elements\n";
538 cout <<
" Global size = " << Map->NumGlobalElements() << endl;
540 cout <<
" Number of elements in [0, " << Lx <<
"] (X-direction): " << nX << endl;
542 cout <<
" Number of interior nodes in the X-direction: " << nX-1 << endl;
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual int NumGlobalNonzeros() const =0
virtual int NumGlobalRows() const =0