21 #include "Epetra_ConfigDefs.h"
22 #include "Epetra_Map.h"
23 #include "Epetra_MultiVector.h"
26 #include "Epetra_MpiComm.h"
29 #include "Epetra_SerialComm.h"
34 #include "ModalAnalysisSolver.h"
37 #include "BlockDACG.h"
39 #include "LOBPCG_light.h"
40 #include "KnyazevLOBPCG.h"
42 #include "ModifiedARPACKm3.h"
46 #include "ModalProblem.h"
47 #include "ModeLaplace1DQ1.h"
48 #include "ModeLaplace1DQ2.h"
49 #include "ModeLaplace2DQ1.h"
50 #include "ModeLaplace2DQ2.h"
51 #include "ModeLaplace3DQ1.h"
52 #include "ModeLaplace3DQ2.h"
54 #include "BlockPCGSolver.h"
55 #include "AMGOperator.h"
56 #include "MyIncompleteChol.h"
59 #include <Teuchos_Assert.hpp>
61 const int LOBPCG_CHOL = 1;
62 const int LOBPCG_LIGHT = 2;
63 const int LOBPCG_AK_CHOL = 3;
64 const int ARPACK_ORIG = 5;
65 const int ARPACK_RESI = 6;
66 const int GALDAVIDSON = 7;
67 const int BRQMIN_CHOL = 9;
68 const int DACG_CHOL = 11;
69 const int JD_PCG = 13;
71 const int NO_PREC = 0;
72 const int AMG_POLYNOMIAL = 1;
73 const int AMG_GAUSSSEIDEL = 2;
74 const int INC_CHOL = 3;
77 int main(
int argc,
char *argv[]) {
85 MPI_Init(&argc,&argv);
86 MPI_Comm_size(MPI_COMM_WORLD, &numProc);
87 MPI_Comm_rank(MPI_COMM_WORLD, &myPid);
94 srand((
unsigned) time(0));
100 double Lx = 1.0, Ly = 1.0, Lz = 1.0;
101 int nX=0, nY=0, nZ=0;
104 int precond = 0, param = 0;
114 bool paramStop =
false;
115 for (i=0; i<numProc; ++i) {
118 ifstream fin(
"control.driver");
121 "driver' could not be opened." );
122 fin >> dimension; fin.getline(buff, 100);
125 fin >> Lx; fin.getline(buff, 100);
126 fin >> nX; fin.getline(buff, 100);
127 fin >> casePb; fin.getline(buff, 100);
130 fin >> Lx >> Ly; fin.getline(buff, 100);
131 fin >> nX >> nY; fin.getline(buff, 100);
132 fin >> casePb; fin.getline(buff, 100);
135 fin >> Lx >> Ly >> Lz; fin.getline(buff, 100);
136 fin >> nX >> nY >> nZ; fin.getline(buff, 100);
137 fin >> casePb; fin.getline(buff, 100);
142 fin >> algo; fin.getline(buff, 100);
143 fin >> precond; fin.getline(buff, 100);
144 fin >> param; fin.getline(buff, 100);
145 fin >> numEigen; fin.getline(buff, 100);
146 fin >> dimSearch; fin.getline(buff, 100);
147 fin >> numBlock; fin.getline(buff, 100);
148 fin >> maxIter; fin.getline(buff, 100);
149 fin >> tol; fin.getline(buff, 100);
150 fin >> maxIterCG; fin.getline(buff, 100);
151 fin >> tolCG; fin.getline(buff, 100);
152 fin >> verbose; fin.getline(buff, 100);
178 case AMG_GAUSSSEIDEL:
186 if ((dimension < 1) && (dimension > 3))
189 if ((casePb != 1) && (casePb != 2))
193 if (paramStop ==
true) {
194 if (verbose*(myPid==0) > 0) {
196 cerr <<
"Usage: prun -n NP ./driver" << endl;
198 cerr <<
"Usage: ./driver.serial" << endl;
201 cerr <<
"Input file: 'control.driver'" << endl;
203 cerr <<
"Example of input file" << endl;
205 cerr <<
"3 Space dimension (1, 2, 3)" << endl;
206 cerr <<
"1.0 2.0 3.0 Lx Ly Lz (Dimension of brick in each direction)" << endl;
207 cerr <<
"10 11 12 nX nY nZ (Number of elements in each direction)" << endl;
208 cerr <<
"1 Case Problem (1=Q1, 2=Q2)" << endl;
209 cerr <<
"1 Algorithm (1 .. 15)" << endl;
210 cerr <<
"1 Preconditioner (0 = None, 1 = AMG Poly, 2 = AMG GS)"
212 cerr <<
"1 Parameter for preconditioner: AMG Poly. Deg."
214 cerr <<
"10 Number of eigenpairs requested" << endl;
215 cerr <<
"5 Dimension of block size" << endl;
216 cerr <<
"4 Number of blocks (ONLY referenced by Davidson (7) and JD-PCG (13))"
218 cerr <<
"1000 Maximum number of iterations for eigensolver" << endl;
219 cerr <<
"1e-06 Tolerance" << endl;
220 cerr <<
"1000 Maximum number of inner iterations (PCG, QMR)" << endl;
221 cerr <<
"1e-07 Tolerance for PCG solve (ONLY referenced in ARPACK)" << endl;
222 cerr <<
"1 Verbose level" << endl;
223 cerr <<
"----------------------------------------------------------------------" << endl;
225 cerr <<
"Eigensolver flags:" << endl;
226 cerr <<
" 1. LOBPCG (RBL & UH version) with Cholesky-based local eigensolver" << endl;
227 cerr <<
" 2. LOBPCG (light version) with Cholesky-based local eigensolver" << endl;
228 cerr <<
" 3. LOBPCG (AK version) with Cholesky-based local eigensolver" << endl;
229 cerr <<
" 5. ARPACK (original version)" << endl;
230 cerr <<
" 6. ARPACK (version with user-provided residual)" << endl;
231 cerr <<
" 7. Generalized Davidson (RBL & UH version)" << endl;
232 cerr <<
" 9. BRQMIN with Cholesky-based local eigensolver" << endl;
233 cerr <<
"11. Block DACG with Cholesky-based local eigensolver" << endl;
234 cerr <<
"13. JDCG (Notay's version of Jacobi-Davidson)" << endl;
236 cerr <<
"The dimension of search space corresponds to" << endl;
237 cerr <<
" * the block size for LOBPCG (1)" << endl;
238 cerr <<
" * NCV for ARPACK (5, 6)" << endl;
239 cerr <<
" * one block size for Generalized Davidson (7)" << endl;
240 cerr <<
" * the block size for BRQMIN (9)" << endl;
241 cerr <<
" * the block size for Block DACG (11)" << endl;
242 cerr <<
" * one block size for Jacobi-Davidson JDCG (13)" << endl;
251 double highMem = currentSize();
253 ModalProblem *testCase;
254 if (dimension == 1) {
256 testCase =
new ModeLaplace1DQ1(Comm, Lx, nX);
258 testCase =
new ModeLaplace1DQ2(Comm, Lx, nX);
260 if (dimension == 2) {
262 testCase =
new ModeLaplace2DQ1(Comm, Lx, nX, Ly, nY);
264 testCase =
new ModeLaplace2DQ2(Comm, Lx, nX, Ly, nY);
266 if (dimension == 3) {
268 testCase =
new ModeLaplace3DQ1(Comm, Lx, nX, Ly, nY, Lz, nZ);
270 testCase =
new ModeLaplace3DQ2(Comm, Lx, nX, Ly, nY, Lz, nZ);
273 highMem = (highMem < currentSize()) ? currentSize() : highMem;
276 if (verbose*(myPid==0) > 0) {
278 testCase->problemInfo();
291 numEigen = (numEigen > globalSize) ? globalSize : numEigen;
293 double *globalWeight = 0;
294 double globalMassMin = 0.0;
296 if (dynamic_cast<ModeLaplace*>(testCase))
297 globalMassMin = dynamic_cast<ModeLaplace*>(testCase)->getFirstMassEigenValue();
300 AMGOperator precML(Comm, M, 0, 10, 1, 3, 0);
301 BlockPCGSolver linMassSolver(Comm, M, 1e-06, 20);
302 linMassSolver.setPreconditioner(&precML);
303 ARPACKm3 eigMassSolver(Comm, &linMassSolver, 1e-03, globalSize);
304 double *lTmp =
new double[6];
307 int massNEV = eigMassSolver.solve(1, QQ, lTmp);
313 "Error in the computation of smallest eigenvalue for "
314 "the mass matrix. Output information from eigensolver"
316 globalMassMin = lTmp[0];
322 globalWeight =
new double[localSize];
323 for (i = 0; i < localSize; ++i) {
324 globalWeight[i] = sqrt(globalMassMin/globalSize);
327 if (verbose*(myPid==0) > 0) {
330 cout.setf(ios::scientific, ios::floatfield);
331 cout <<
" Smallest eigenvalue for the mass matrix: " << globalMassMin << endl;
340 qSize = dimSearch + numEigen;
344 dimSearch = numEigen;
348 if (dimSearch <= numEigen)
349 dimSearch = 2*numEigen;
353 numBlock = (numBlock <= 0) ? 1 : numBlock;
354 qSize = dimSearch*(numBlock+1);
357 qSize = dimSearch + numEigen;
360 qSize = dimSearch + numEigen;
363 numBlock = (numBlock <= 0) ? 1 : numBlock;
364 qSize = dimSearch*(numBlock+1);
368 double *vQ =
new (nothrow)
double[qSize*localSize];
371 double *lambda =
new (nothrow)
double[qSize];
377 highMem = (highMem > currentSize()) ? highMem : currentSize();
380 MyIncompleteChol *ICT = 0;
381 BlockPCGSolver *opStiffness =
new BlockPCGSolver(Comm, K, tolCG, maxIterCG,
382 (verbose) ? verbose-1 : 0);
383 AMGOperator *precML = 0;
386 opStiffness->setPreconditioner(0);
387 strcpy(precLabel,
" No preconditioner");
393 precML =
new AMGOperator(Comm, K, verbose, 10, 1, param, 0);
394 opStiffness->setPreconditioner(precML);
395 strcpy(precLabel,
" AMG with polynomial smoother");
397 case AMG_GAUSSSEIDEL:
399 precML =
new AMGOperator(Comm, K, verbose, 10, 2, param, 0);
400 opStiffness->setPreconditioner(precML);
401 strcpy(precLabel,
" AMG with Gauss-Seidel smoother");
406 if (dynamic_cast<Epetra_CrsMatrix*>(KOp)) {
407 ICT =
new MyIncompleteChol(Comm, KOp, Epetra_MinDouble, param);
411 cerr <<
" !!! The incomplete Cholesky factorization can not be done !!!\n";
412 cerr <<
" !!! No preconditioner is used !!!\n";
415 opStiffness->setPreconditioner(ICT);
417 strcpy(precLabel,
" Incomplete Cholesky factorization");
422 ModalAnalysisSolver *mySolver;
426 mySolver =
new LOBPCG(Comm, opStiffness, M, opStiffness->getPreconditioner(),
427 dimSearch, tol, maxIter, verbose, globalWeight);
430 mySolver =
new LOBPCG_light(Comm, opStiffness, M, opStiffness->getPreconditioner(),
431 dimSearch, tol, maxIter, verbose, globalWeight);
434 mySolver =
new KnyazevLOBPCG(Comm, opStiffness, M, opStiffness->getPreconditioner(),
435 tol, maxIter, verbose, globalWeight);
438 mySolver =
new ARPACKm3(Comm, opStiffness, M, tol, maxIter, verbose);
441 mySolver =
new ModifiedARPACKm3(Comm, opStiffness, M, tol, maxIter, verbose,
445 mySolver =
new Davidson(Comm, opStiffness, M, opStiffness->getPreconditioner(),
446 dimSearch, numBlock, tol, maxIter, verbose, globalWeight);
449 mySolver =
new BRQMIN(Comm, opStiffness, M, opStiffness->getPreconditioner(),
450 dimSearch, tol, maxIter, verbose, globalWeight);
453 mySolver =
new BlockDACG(Comm, opStiffness, M, opStiffness->getPreconditioner(),
454 dimSearch, tol, maxIter, verbose, globalWeight);
457 mySolver =
new JDPCG(Comm, opStiffness, M, opStiffness->getPreconditioner(),
458 dimSearch, numBlock, tol, maxIter, maxIterCG, verbose, globalWeight);
463 int knownEV = mySolver->solve(numEigen, Q, lambda);
470 cerr <<
" !!! The eigensolver exited with error " << knownEV <<
" !!! " << endl;
476 if (verbose*(myPid == 0) > 1) {
478 cout <<
" ---------------------------------------------------- \n";
479 cout <<
" History of Computation \n";
480 cout <<
" ---------------------------------------------------- \n";
482 mySolver->algorithmInfo();
483 cout <<
" Preconditioner: " << precLabel << endl;
485 testCase->problemInfo();
486 cout <<
" Number of computed eigenmodes: " << knownEV << endl;
487 mySolver->historyInfo();
492 int nb = (knownEV > numEigen) ? numEigen : knownEV;
496 cout <<
" ---------------------------------------------------- \n";
497 cout <<
" Eigenpairs accuracy \n";
498 cout <<
" ---------------------------------------------------- \n";
500 mySolver->algorithmInfo();
501 cout <<
" Preconditioner: " << precLabel << endl;
503 testCase->problemInfo();
504 cout <<
" Number of computed eigenmodes: " << copyQ.NumVectors() << endl;
506 cout.setf(ios::scientific, ios::floatfield);
507 cout <<
" Tolerance on residuals: " << tol << endl;
509 cout <<
" Smallest eigenvalue for the mass matrix: " << globalMassMin << endl;
512 testCase->eigenCheck(copyQ, lambda, globalWeight);
518 cout <<
" ---------------------------------------------------- \n";
519 cout <<
" Summary of statistics \n";
520 cout <<
" ---------------------------------------------------- \n";
522 mySolver->algorithmInfo();
523 cout <<
" Preconditioner: " << precLabel << endl;
525 testCase->problemInfo();
526 cout <<
" Number of computed eigenmodes: " << knownEV << endl;
528 cout.setf(ios::scientific, ios::floatfield);
529 cout <<
" Tolerance on residuals: " << tol << endl;
530 if ((algo == ARPACK_ORIG) || (algo == ARPACK_RESI)) {
531 cout <<
" Size of Search Space: " << dimSearch << endl;
534 cout.setf(ios::scientific, ios::floatfield);
535 cout <<
" Tolerance on PCG solves: " << tolCG << endl;
537 cout <<
" Minimum number of PCG iterations per solve: ";
538 cout << opStiffness->getMinIter() << endl;
539 cout.setf(ios::fixed, ios::floatfield);
540 cout <<
" Average number of PCG iterations per solve: ";
541 cout << opStiffness->getAvgIter() << endl;
542 cout <<
" Maximum number of PCG iterations per solve: ";
543 cout << opStiffness->getMaxIter() << endl;
546 if (precond == AMG_POLYNOMIAL) {
547 cout <<
" Number of levels for AMG preconditioner: ";
548 cout << precML->getAMG_NLevels() << endl;
549 cout <<
" Polynomial degree of AMG preconditioner: " << param << endl;
552 if (precond == AMG_GAUSSSEIDEL) {
553 cout <<
" Number of levels for AMG preconditioner: ";
554 cout << precML->getAMG_NLevels() << endl;
557 if ((precond == INC_CHOL) && (ICT)) {
558 cout <<
" Level of fill for incomplete Cholesky factorisation: ";
559 cout << param << endl;
562 cout <<
" Number of processors: " << numProc << endl;
567 double maxHighMem = 0.0;
568 Comm.
MaxAll(&highMem, &maxHighMem, 1);
570 cout <<
" --- Memory ---\n";
573 cout.setf(ios::fixed, ios::floatfield);
574 cout <<
" High water mark in set-up = (EST) ";
575 cout << maxHighMem <<
" MB\n";
579 testCase->memoryInfo();
583 cout.setf(ios::fixed, ios::floatfield);
584 cout <<
" Memory requested per processor for eigenvectors = (EST) ";
585 cout << Q.GlobalLength()*numEigen*
sizeof(double)/1024.0/1024.0/numProc;
588 cout <<
" Memory requested per processor for working space = (EST) ";
589 cout << Q.GlobalLength()*(Q.NumVectors()-numEigen)*
sizeof(
double)/1024.0/1024.0/numProc;
594 mySolver->memoryInfo();
596 mySolver->operationInfo();
598 mySolver->timeInfo();
610 delete[] globalWeight;
int NumGlobalElements() const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual const Epetra_Map & OperatorDomainMap() const =0
int NumMyElements() const
int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const