int main(int argc, char* argv[]) { #ifdef CH_MPI MPI_Init (&argc, &argv); #endif // test parameters const int nGrids = 3; const int nCells0 = 32; // xLo has to be zero in order for DiriBc to work. const RealVect xLo = RealVect::Zero; const Real xHi = 1.0; const Box box0(IntVect::Zero, (nCells0-1)*IntVect::Unit); const int nGhosts = 1; const int resNT = 2; // norm Type const int errNT = 0; // A test is considered as a failure // if its convergence rate is smaller than below. const Real targetConvergeRate = 1.75; // solver parameters // To converge within 10 V-Cycles in 1D, // nRelax=3 is the minimum number of relaxations. const int nRelax = 3; // m_pre=m_post // cycle Type, 1 : V-Cycle; -1 : FMG-Cycle const int cycleType[2] = { 1, -1 }; const std::string cycleStr[2] = { " V" , " FMG" }; // test results holder const int nCycles[2] = { 9, 5 }; const int maxCycles = 10; // > max(nCycles) // Real resNorm[nGrids][nCycles+1], errNorm[nGrids][nCycles+1]; Real resNorm[nGrids][maxCycles], errNorm[nGrids][maxCycles]; Real convergeRate[nGrids-1][2]; const Real log2r = 1.0/log(2.0); // status records the number of errors detected. int status = 0; for (int j=0; j<2; j++) { pout() << "\n**************************************************\n" << "\nTesting MultiGrid::oneCycle(correction, residual)\n" << " cycle type = " << cycleStr[j] << "; m_pre = m_post = " << nRelax << "\n"; for (int iGrid=0; iGrid<nGrids; iGrid++) { int ref = 1; for (int i=0; i<iGrid; i++) ref*=2; const Real dx = xHi/nCells0/ref; const Box domain = refine(box0,ref); const Box ghostBox = grow(domain,nGhosts); pout() << "\n----------------------------------------------------\n"; pout() << "nCells = " << nCells0*ref << " ; dx = " << dx << " \n"; FArrayBox phi(ghostBox, 1); FArrayBox correction(ghostBox, 1); FArrayBox rhs(domain, 1); FArrayBox error(domain, 1); FArrayBox phiExact(domain, 1); FArrayBox residual(domain, 1); // set initial guess phi.setVal(0.0); // set RHS and the exact solution for (BoxIterator bit(domain); bit.ok(); ++bit) { const RealVect offset = bit()-domain.smallEnd(); const RealVect x = xLo + dx*(0.5+offset); rhs(bit()) = rhsFunc( x ); phiExact(bit()) = exactSolution( x ); } // Initialize big objects NewPoissonOpFactory opFactory; opFactory.define(dx*RealVect(IntVect::Unit), constDiriBC); MultiGrid<FArrayBox> solver; BiCGStabSolver<FArrayBox> bottomSolver; bottomSolver.m_verbosity = 0; MGLevelOp<FArrayBox>* op = opFactory.MGnewOp(domain,0); solver.m_numMG = 1; solver.m_bottom = 1; solver.m_pre = nRelax; solver.m_post = nRelax; solver.m_cycle = cycleType[j]; solver.define(opFactory, &bottomSolver, domain); // put the data into residual-correction form op->residual(residual, phi, rhs); resNorm[iGrid][0] = residual.norm(resNT); op->axby(error, phi, phiExact, 1, -1); errNorm[iGrid][0] = error.norm(errNT); solver.init(correction, residual); // Solve the problem using MultiGrid::oneCycle for (int i=0; i<nCycles[j]; i++) { correction.setVal(0.0); solver.oneCycle(correction, residual); op->incr(phi, correction, 1); op->residual(residual, phi, rhs); resNorm[iGrid][i+1] = residual.norm(resNT); op->axby(error, phi, phiExact, 1, -1); errNorm[iGrid][i+1] = error.norm(errNT); } delete op; // output a table of results pout()<< cycleStr[j] << "-Cycle N.O. | residual " << resNT << "-norm | Error " << errNT << "-norm \n"; for (int i=0; i<nCycles[j]+1; i++) { pout() << " " << i << " | " << resNorm[iGrid][i] << " | " << errNorm[iGrid][i] << "\n"; } } // end grid loop pout() << "\nConvergence Rate based on the error in the last cycle:\n"; for (int i=0; i<nGrids-1; i++) { Real ratio = errNorm[i][nCycles[j]]/errNorm[i+1][nCycles[j]]; convergeRate[i][j] = log(ratio)*log2r; if (convergeRate[i][j] < targetConvergeRate) { status += 1; } pout() << " " << convergeRate[i][j] << "\n"; } }// end cycle type if (status==0) { pout() << "All tests passed!\n"; } else { pout() << status << " tests failed!\n"; } #ifdef CH_MPI MPI_Finalize (); #endif return status; }
// Constant Dirichlet Boundary condition void constDiri(Real* pos, int* dir, Side::LoHiSide* side, Real* a_values) { a_values[0] = exactSolution(RealVect(D_DECL(pos[0], pos[1], pos[2]))); }
PetscErrorCode go(int nGrids, int &status) { CH_TIME("go"); PetscErrorCode ierr; Real errNorm[20][2]; Real convergeRate[20-1][2]; bool sameGrids; const Real log2r = 1.0/log(2.0); const Real targetConvergeRate = 2*0.9; Vector<RefCountedPtr<LevelData<FArrayBox> > > phi; Vector<RefCountedPtr<LevelData<FArrayBox> > > rhs; Vector<LevelData<FArrayBox> *> phi2; Vector<LevelData<FArrayBox> *> rhs2; Vector<RefCountedPtr<LevelData<FArrayBox> > > exact; Vector<int> refratios; Vector<ProblemDomain> domains; Vector<DisjointBoxLayout> grids; Vector<IntVectSet> tagVects(nGrids-1); Real cdx,dx; PetscCompGridPois petscop(0.,-1.,s_order); RefCountedPtr<ConstDiriBC> bcfunc = RefCountedPtr<ConstDiriBC>(new ConstDiriBC(2,petscop.getGhostVect())); BCHolder bc(bcfunc); PetscFunctionBeginUser; petscop.setCornerStencil(s_corner_stencil); petscop.setMatlab(s_matlab); for (int nLev=1,iMaxLev=0; nLev<=nGrids; nLev++,iMaxLev++) { ierr = setupGrids( refratios, domains, grids, nLev, cdx, exact, phi, iMaxLev==0 ? 0.: errNorm[iMaxLev-1][0], tagVects, sameGrids ); CHKERRQ(ierr); if (sameGrids){ nGrids = iMaxLev; break;} // allocate vectors, set RHS and exact phi.resize(nLev); rhs.resize(nLev); exact.resize(nLev); phi2.resize(nLev); rhs2.resize(nLev); dx = cdx; for (int ilev=0;ilev<nLev;ilev++) { phi[ilev] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>(grids[ilev],COMP_POIS_DOF,petscop.getGhostVect())); rhs[ilev] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>(grids[ilev],COMP_POIS_DOF,IntVect::Zero)); exact[ilev] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>(grids[ilev],COMP_POIS_DOF,IntVect::Unit)); rhs2[ilev] = &(*rhs[ilev]); phi2[ilev] = &(*phi[ilev]); const DisjointBoxLayout &dbl = grids[ilev]; for (DataIterator dit(dbl) ; dit.ok(); ++dit) { FArrayBox& rhsFAB = (*rhs[ilev])[dit]; Box region = dbl[dit]; for (BoxIterator bit(region); bit.ok(); ++bit) { IntVect iv = bit(); RealVect loc(iv); loc *= dx; loc += 0.5*dx*RealVect::Unit; for (int i=0;i<COMP_POIS_DOF;i++) rhsFAB(iv,i) = rhsFunc(loc); } FArrayBox& exactfab = (*exact[ilev])[dit]; FArrayBox& phifab = (*phi[ilev])[dit]; Box eregion = exactfab.box(); for (BoxIterator bit(eregion); bit.ok(); ++bit) { IntVect iv = bit(); RealVect loc(iv); loc *= dx; loc += 0.5*dx*RealVect::Unit; for (int i=0;i<COMP_POIS_DOF;i++) exactfab(iv,i) = exactSolution(loc); } phifab *= .0; } if (ilev!=nLev-1) dx /= refratios[ilev]; } // form matrix petscop.define(domains[0],grids,refratios,bc,cdx*RealVect::Unit); petscop.setVerbose(1); ierr = petscop.createMatrix(); CHKERRQ(ierr); // solve Vec x, b; /* approx solution, RHS */ { CH_TIME("PETSC-solve"); Mat A; /* linear system matrix */ KSP ksp; /* linear solver context */ A = petscop.getMatrix(); ierr = MatGetVecs(A,&x,&b); CHKERRQ(ierr); ierr = petscop.putChomboInPetsc(rhs2,b); CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &ksp); CHKERRQ(ierr); #if PETSC_VERSION_GE(3,5,0) ierr = KSPSetOperators(ksp, A, A); CHKERRQ(ierr); #else ierr = KSPSetOperators(ksp, A, A, DIFFERENT_NONZERO_PATTERN); CHKERRQ(ierr); #endif ierr = KSPSetFromOptions(ksp); CHKERRQ(ierr); ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr); ierr = KSPDestroy(&ksp); CHKERRQ(ierr); } if (s_plot) { ierr = plotAll(phi2,rhs2,exact,errNorm[iMaxLev],"testPetscCompGrid.", cdx,grids,refratios,domains,petscop,x,nLev); CHKERRQ(ierr); } ierr = VecDestroy(&x); CHKERRQ(ierr); ierr = VecDestroy(&b); CHKERRQ(ierr); } // #ifdef CH_USE_FAS // do AMRFAS if (s_amrfas) { int status; AMRFAS<LevelData<FArrayBox> > amrFASSolver; FASPoissonOpFactory opFactory(2); // solving poisson problem here opFactory.define( bc, 0., -1. ); amrFASSolver.m_pre = 4; amrFASSolver.m_post = 4; amrFASSolver.m_verbosity = 5; s_fas_verbosity = 1; // this is in AMRFASI.H amrFASSolver.setAvoidNorms(false); amrFASSolver.setInternalCoarseningRate(2); amrFASSolver.setNumVcycles(1); amrFASSolver.setCycleType(FAS_FULL); amrFASSolver.m_max_iter = 100; amrFASSolver.m_atol = 1.0e-9; amrFASSolver.m_rtol = 1.0e-9; amrFASSolver.m_stagnate = 1.e-2; amrFASSolver.setSmootherType(FAS_RICH); amrFASSolver.setSmoothingDampingFactor(CH_SPACEDIM==3 ? .7 : .8); amrFASSolver.setFMGProlOrderP(2); amrFASSolver.setProlOrderP(1); amrFASSolver.define( domains[0], cdx*RealVect::Unit, grids, refratios, opFactory ); for (int ilev=0;ilev<nGrids;ilev++) { const DisjointBoxLayout &dbl = grids[ilev]; for (DataIterator dit(dbl) ; dit.ok(); ++dit) { FArrayBox& fab = (*phi[ilev])[dit]; fab.setVal(0.0,dbl[dit],0,fab.nComp()); } } amrFASSolver.solve( phi, rhs, &status ); PetscCompGridPois petscop(0.,-1.,2); petscop.define(domains[0],grids,refratios,bc,cdx*RealVect::Unit); Real errNorms[2]; ierr = plotAll( phi2,rhs2,exact,errNorms,"testPetscCompGridAMRFAS.", cdx,grids,refratios,domains,petscop,PETSC_NULL,nGrids); CHKERRQ(ierr); } #endif // do AMRMultigrid if (s_amrmg) { AMRMultiGrid<LevelData<FArrayBox> > amrMG; AMRPoissonOpFactory opFactory; BiCGStabSolver<LevelData<FArrayBox> > biCGStab; PetscCompGridPois petscop(0.,-1.,2); petscop.define(domains[0],grids,refratios,bc,cdx*RealVect::Unit); // solving poisson problem here opFactory.define( domains[0], grids, refratios, cdx, bc, 0., -1. ); amrMG.define( domains[0], opFactory, &biCGStab, nGrids); amrMG.setSolverParameters(4,4,100,1,100,1.0e-9,1.0e-9,1.0e-9); amrMG.m_verbosity = 3; amrMG.solve( phi2, rhs2, nGrids-1, 0, true, true ); Real errNorms[2]; ierr = plotAll( phi2,rhs2,exact,errNorms,"testPetscCompGridGMG.", cdx,grids,refratios,domains,petscop,PETSC_NULL,nGrids); CHKERRQ(ierr); } pout() << "\nConvergence Rates : Inf norm 1 norm\n"; pout() << "----------------------------------------\n" << std::setprecision(3); if (s_plot) { for (int i=0; i<nGrids-1; i++) { pout() << " "; for (int j=0;j<2;j++) { const Real ratio = errNorm[i][j]/errNorm[i+1][j]; convergeRate[i][j] = log(ratio)*log2r; if (j==1)convergeRate[i][j] *= 2; // this is not quite right if (convergeRate[i][j] < targetConvergeRate && i>0 ) // first test misses because of griding { status += 1; } pout() << " " << convergeRate[i][j]; } pout() << endl; } if (status==0) { pout() << "All tests passed!\n"; } else { pout() << status << " tests failed!\n"; } } PetscFunctionReturn(0); }
real Problem::ub( int region, real x, real y ) const { return 2 * y + exactSolution( region, x, y ); }
int main(int argc, char* argv[]) { if (argc != 2) { std::cout << "Proper usage ./prog numThreads" << std::endl; return 1; } int numThreads = strtof(argv[1], NULL); for(int i=1; i<m-1; i++) { for (int j = 1; j < n-1; j++) { Un[i][j]=0.0; } } for (int i = 0; i < m; i++) { Un[i][0] = exactSolution(x(i), y(0)); Un[i][n -1] = exactSolution(x(i), y(n - 1)); Unp1[i][0] = exactSolution(x(i), y(0)); Unp1[i][n -1] = exactSolution(x(i), y(n - 1)); } for (int i = 0; i < n; i++) { Un[0][i] = exactSolution(x(0), y(i)); Un[m - 1][i] = exactSolution(x(m-1), y(i)); Unp1[0][i] = exactSolution(x(0), y(i)); Unp1[m - 1][i] = exactSolution(x(m-1), y(i)); } int iterations=0; double iterationError = 1.; double time = omp_get_wtime(); while(iterationError > tolerance && iterations < maxIterations) { iterations++; // // if(iterations % 1000 == 0) std::cout<<"iteration " << iterations << std::endl; #pragma omp parallel for num_threads(numThreads) for(int i=1; i< m-1; i++) { for (int j = 1; j < n -1; j++) { Unp1[i][j] = (dy*dy*dx*dx*S(x(i), y(j)) - \ dy*dy*(Un[i -1][j] + Un[i + 1][j]) - \ dx*dx*(Un[i][j -1] + Un[i][j+1])) / (-2*dy*dy - 2*dx*dx); } } iterationError=0.0; // Calculate diff between Un, Up+1 #pragma omp parallel for num_threads(numThreads) for(int i = 0; i< m; i++) { for (int j = 0; j < n; j++) { error[i][j] = fabs(Unp1[i][j] - Un[i][j]); } } for (int i = 0; i<m; i++) for (int j = 0; j <n; j++) iterationError = (iterationError > error[i][j] ? iterationError : error[i][j]); // Testing revealed it was faster to *NOT* parallelize this loop. for(int i=0; i < m; i++) { for (int j = 0; j < n; j++) { Un[i][j] = Unp1[i][j]; } } // if(iterations % 1000 == 0) std::cout<< "The error between two iterates is " << iterationError << std::endl; } double time2 = omp_get_wtime(); double solution_error=0.0; for(int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { double local_solution_error=fabs(Unp1[i][j]- exactSolution(x(i), y(j)) ); { if (local_solution_error > solution_error) solution_error = local_solution_error; } } } // Output: std::cout << std::endl << std::endl; std::cout<< "-------------------------------------------------------" << std::endl; std::cout<< "SUMMARY:" << std::endl << std::endl; std::cout<< "The error between two iterates is " << iterationError << std::endl << std::endl; std::cout<< "The maximum error in the solution is " << solution_error << std::endl; std::cout<< "The time taken is " << time2 - time << std::endl; std::cout<< "-------------------------------------------------------" << std::endl << std::endl; return 0; }