Example #1
0
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;
}
Example #2
0
// 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])));
}
Example #3
0
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 );
}
Example #5
0
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;
}