Esempio n. 1
0
int main(int argc,char **argv)
{
  PetscErrorCode ierr;
  DM             da;                   /* structured grid topology object */
  TS             ts;                   /* time-stepping object (contains snes) */
  SNES           snes;                 /* Newton solver object */
  Vec            X,residual;           /* solution, residual */
  Mat            J;                    /* Jacobian matrix */
  PetscInt       Mx,My,fsteps,steps;
  ISColoring     iscoloring;
  PetscReal      tstart,tend,ftime,secperday=3600.0*24.0,Y0;
  PetscBool      fdflg = PETSC_FALSE, mfileflg = PETSC_FALSE, optflg = PETSC_FALSE;
  char           mfile[PETSC_MAX_PATH_LEN] = "out.m";
  MatFDColoring  matfdcoloring;
  PorousCtx      user;                 /* user-defined work context */

  PetscInitialize(&argc,&argv,(char *)0,help);

  ierr = DMDACreate2d(PETSC_COMM_WORLD,
             DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, // correct for zero Dirichlet
             DMDA_STENCIL_STAR, // nonlinear diffusion but diffusivity
                                //   depends on soln W not grad W
             -21,-21,           // default to 20x20 grid but override with
                                //   -da_grid_x, -da_grid_y (or -da_refine)
             PETSC_DECIDE,PETSC_DECIDE, // num of procs in each dim
             2,                 // dof = 2:  node = (W,Y)
                                //        or node = (P,dPsqr)
                                //        or node = (ddxE,ddyN)
             1,                 // s = 1 (stencil extends out one cell)
             PETSC_NULL,PETSC_NULL, // no specify proc decomposition
             &da);CHKERRQ(ierr);
  ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr);

  /* get Vecs and Mats for this grid */
  ierr = DMCreateGlobalVector(da,&X);CHKERRQ(ierr);
  ierr = VecDuplicate(X,&residual);CHKERRQ(ierr);
  ierr = VecDuplicate(X,&user.geom);CHKERRQ(ierr);
  ierr = DMGetMatrix(da,MATAIJ,&J);CHKERRQ(ierr);

  /* set up contexts */
  tstart   = 10.0 * secperday; /* 10 days in seconds */
  tend     = 30.0 * secperday;
  steps    = 20;
  Y0       = 1.0;              /* initial value of Y, for computing initial
                                  value of P; note Ymin = 0.1 is different */
  user.da = da;
  ierr = DefaultContext(&user);CHKERRQ(ierr);

  ierr = PetscOptionsBegin(PETSC_COMM_WORLD,
           "","options to (W,P)-space better hydrology model alt","");CHKERRQ(ierr);
  {
    ierr = PetscOptionsReal("-alt_sigma","nonlinear power","",
                            user.sigma,&user.sigma,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_Ymin",
                            "min capacity thickness (esp. in pressure computation)","",
                            user.Ymin,&user.Ymin,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_Wmin",
                            "min water amount (esp. in pressure computation)","",
                            user.Wmin,&user.Wmin,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_Y0",
                            "constant initial capacity thickness","",
                            Y0,&Y0,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_Cmelt",
                            "additional coefficient for amount of melt","",
                            user.Cmelt,&user.Cmelt,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_Creep",
                            "creep closure coefficient","",
                            user.Creep,&user.Creep,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_L","half-width of square region in meters","",
                            user.L,&user.L,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsReal("-alt_tstart_days","start time in days","",
                            tstart/secperday,&tstart,&optflg);CHKERRQ(ierr);
    if (optflg) { tstart *= secperday; }
    ierr = PetscOptionsReal("-alt_tend_days","end time in days","",
                            tend/secperday,&tend,&optflg);CHKERRQ(ierr);
    if (optflg) { tend *= secperday; }
    ierr = PetscOptionsInt("-alt_steps","number of timesteps to take","",
                           steps,&steps,PETSC_NULL);CHKERRQ(ierr);
    ierr = PetscOptionsBool("-alt_converge_check",
                            "run silent and check for convergence",
                            "",user.run_silent,&user.run_silent,PETSC_NULL);
                            CHKERRQ(ierr);
    ierr = PetscOptionsString("-mfile",
                            "name of Matlab file to write results","",
                            mfile,mfile,PETSC_MAX_PATH_LEN,&mfileflg);
                            CHKERRQ(ierr);
  }
  ierr = PetscOptionsEnd();CHKERRQ(ierr);

  /* fix remaining parameters */
  ierr = DerivedConstants(&user);CHKERRQ(ierr);
  ierr = VecStrideSet(user.geom,0,user.H0);CHKERRQ(ierr);  /* H(x,y) = H0 */
  ierr = VecStrideSet(user.geom,1,0.0);CHKERRQ(ierr);      /* b(x,y) = 0  */
  ierr = DMDASetUniformCoordinates(da,  // square domain
              -user.L, user.L, -user.L, user.L, 0.0, 1.0);CHKERRQ(ierr);
  ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,
            PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
            PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
            PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
  user.dx = 2.0 * user.L / (Mx-1);
  user.dy = 2.0 * user.L / (My-1);

  /* setup TS = timestepping object */
  ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
  ierr = TSSetType(ts,TSCN);CHKERRQ(ierr);
  ierr = TSSetRHSFunction(ts,residual,RHSFunction,&user);CHKERRQ(ierr);

  /* use coloring to compute rhs Jacobian efficiently */
  ierr = PetscOptionsGetBool(PETSC_NULL,"-fd",&fdflg,PETSC_NULL);CHKERRQ(ierr);
  if (fdflg){
    ierr = DMGetColoring(da,IS_COLORING_GLOBAL,MATAIJ,&iscoloring);CHKERRQ(ierr);
    ierr = MatFDColoringCreate(J,iscoloring,&matfdcoloring);CHKERRQ(ierr);
    ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr);
    ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
    ierr = MatFDColoringSetFunction(matfdcoloring,
             (PetscErrorCode (*)(void))RHSFunction,&user);CHKERRQ(ierr);
    ierr = TSSetRHSJacobian(ts,J,J,TSDefaultComputeJacobianColor,
             matfdcoloring);CHKERRQ(ierr);
  } else { /* default case */
    ierr = TSSetRHSJacobian(ts,J,J,RHSJacobian,&user);CHKERRQ(ierr);
  }

  /* set initial state:  W = barenblatt, P = pi (W/Y0)^sigma */
  ierr = InitialState(da,&user,tstart,Y0,X);CHKERRQ(ierr);

  /* set up times for time-stepping */
  ierr = TSSetInitialTimeStep(ts,tstart,
           (tend - tstart) / (PetscReal)steps);CHKERRQ(ierr);
  ierr = TSSetDuration(ts,steps,tend);CHKERRQ(ierr);
  ierr = TSSetExactFinalTime(ts,PETSC_TRUE);CHKERRQ(ierr);
  ierr = TSMonitorSet(ts,MyTSMonitor,&user,PETSC_NULL);CHKERRQ(ierr);

  /* Set SNESVI type and supply upper and lower bounds. */
  ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
  ierr = SNESVISetComputeVariableBounds(snes,FormPositivityBounds);
        CHKERRQ(ierr);

  /* ask user to finalize settings */
  ierr = TSSetFromOptions(ts);CHKERRQ(ierr);

  /* report on setup */
  if (!user.run_silent) {
    ierr = PetscPrintf(PETSC_COMM_WORLD,
      "setup done: square       side length = %.3f km\n"
      "            grid               Mx,My = %d,%d\n"
      "            spacing            dx,dy = %.3f,%.3f m\n"
      "            times     tstart:dt:tend = %.3f:%.3f:%.3f days\n",
      2.0 * user.L / 1000.0, Mx, My, user.dx, user.dy,
      tstart / secperday, (tend-tstart)/(steps*secperday), tend / secperday);
      CHKERRQ(ierr);
  }
  if (mfileflg) {
    if (!user.run_silent) {
      ierr = PetscPrintf(PETSC_COMM_WORLD,
        "writing initial W,P and geometry H,b to Matlab file %s ...\n",
        mfile);CHKERRQ(ierr);
    }
    ierr = print2vecmatlab(da,X,"W_init","P_init",mfile,PETSC_FALSE);CHKERRQ(ierr);
    ierr = print2vecmatlab(da,user.geom,"H","b",mfile,PETSC_TRUE);CHKERRQ(ierr);
  }

  /* run time-stepping with implicit steps  */
  ierr = TSSolve(ts,X,&ftime);CHKERRQ(ierr);

  /* make a report on run and final state */
  ierr = TSGetTimeStepNumber(ts,&fsteps);CHKERRQ(ierr);
  if ((!user.run_silent) && (ftime != tend)) {
    ierr = PetscPrintf(PETSC_COMM_WORLD,
    "***WARNING3***:  reported final time wrong:  ftime(=%.12e) != tend(=%.12e) (days)\n",
    ftime / secperday, tend / secperday);CHKERRQ(ierr); }
  if ((!user.run_silent) && (fsteps != steps)) {
    ierr = PetscPrintf(PETSC_COMM_WORLD,
    "***WARNING4***:  reported number of steps wrong:  fsteps(=%D) != steps(=%D)\n",
    fsteps, steps);CHKERRQ(ierr); }

  if (mfileflg) {
    if (!user.run_silent) {
      ierr = PetscPrintf(PETSC_COMM_WORLD,
        "writing final fields to %s ...\n",mfile);CHKERRQ(ierr);
    }
    ierr = print2vecmatlab(da,X,"W_final","P_final",mfile,PETSC_TRUE);CHKERRQ(ierr);
    ierr = printfigurematlab(da,2,"W_init","W_final",mfile,PETSC_TRUE);CHKERRQ(ierr);
    ierr = printfigurematlab(da,3,"P_init","P_final",mfile,PETSC_TRUE);CHKERRQ(ierr);
  }

  if (user.run_silent) {
    ierr = PetscPrintf(PETSC_COMM_WORLD, "%6d  %6d  %9.3f  %.12e\n",
                       Mx, My, (tend-tstart)/secperday, user.maxrnorm);CHKERRQ(ierr);
  }

  /* Free work space.  */
  ierr = MatDestroy(&J);CHKERRQ(ierr);
  if (fdflg) { ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr); }
  ierr = VecDestroy(&X);CHKERRQ(ierr);
  ierr = VecDestroy(&user.geom);CHKERRQ(ierr);
  ierr = VecDestroy(&residual);CHKERRQ(ierr);
  ierr = TSDestroy(&ts);CHKERRQ(ierr);
  ierr = DMDestroy(&da);CHKERRQ(ierr);

  ierr = PetscFinalize();CHKERRQ(ierr);

  PetscFunctionReturn((PetscInt)(user.not_converged_warning));
}
Esempio n. 2
0
/*@C
    DMMGSetKSP - Sets the linear solver object that will use the grid hierarchy

    Collective on DMMG

    Input Parameter:
+   dmmg - the context
.   func - function to compute linear system matrix on each grid level
-   rhs - function to compute right hand side on each level (need only work on the finest grid
          if you do not use grid sequencing)

    Level: advanced

    Notes: For linear problems my be called more than once, reevaluates the matrices if it is called more
       than once. Call DMMGSolve() directly several times to solve with the same matrix but different 
       right hand sides.
   
.seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), DMMGSetMatType()

@*/
PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetKSP(DMMG *dmmg,PetscErrorCode (*rhs)(DMMG,Vec),PetscErrorCode (*func)(DMMG,Mat,Mat))
{
  PetscErrorCode ierr;
  PetscInt       i,nlevels = dmmg[0]->nlevels,level;
  PetscTruth     ismg,galerkin=PETSC_FALSE;
  PC             pc;
  KSP            lksp;
  
  PetscFunctionBegin;
  if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");

  if (!dmmg[0]->ksp) {
    /* create solvers for each level if they don't already exist*/
    for (i=0; i<nlevels; i++) {

      ierr = KSPCreate(dmmg[i]->comm,&dmmg[i]->ksp);CHKERRQ(ierr);
      ierr = PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->ksp,PETSC_NULL,nlevels-i);CHKERRQ(ierr);
      ierr = KSPSetOptionsPrefix(dmmg[i]->ksp,dmmg[i]->prefix);CHKERRQ(ierr);
      ierr = DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);CHKERRQ(ierr);
      ierr = KSPSetFromOptions(dmmg[i]->ksp);CHKERRQ(ierr);

      /*  if the multigrid is being run with Galerkin then these matrices do not need to be created except on the finest level
          we do not take advantage of this because it may be that Galerkin has not yet been selected for the KSP object 
          These are also used if grid sequencing is selected for the linear problem. We should probably turn off grid sequencing
          for the linear problem */
      if (!dmmg[i]->B) {
	ierr = DMGetMatrix(dmmg[i]->dm,dmmg[nlevels-1]->mtype,&dmmg[i]->B);CHKERRQ(ierr);
      } 
      if (!dmmg[i]->J) {
	dmmg[i]->J = dmmg[i]->B;
	ierr = PetscObjectReference((PetscObject) dmmg[i]->J);CHKERRQ(ierr);
      }

      dmmg[i]->solve = DMMGSolveKSP;
      dmmg[i]->rhs   = rhs;
    }
  }

  /* evalute matrix on each level */
  ierr = KSPGetPC(dmmg[nlevels-1]->ksp,&pc);CHKERRQ(ierr);
  ierr = PetscTypeCompare((PetscObject)pc,PCMG,&ismg);CHKERRQ(ierr);
  if (ismg) {
    ierr = PCMGGetGalerkin(pc,&galerkin);CHKERRQ(ierr);
  }
  if (func) {
    if (galerkin) {
      ierr = (*func)(dmmg[nlevels-1],dmmg[nlevels-1]->J,dmmg[nlevels-1]->B);CHKERRQ(ierr);
    } else {
      for (i=0; i<nlevels; i++) {
        ierr = (*func)(dmmg[i],dmmg[i]->J,dmmg[i]->B);CHKERRQ(ierr);
      }
    }
  }

  for (i=0; i<nlevels-1; i++) {
    ierr = KSPSetOptionsPrefix(dmmg[i]->ksp,"dmmg_");CHKERRQ(ierr);
  }

  for (level=0; level<nlevels; level++) {
    ierr = KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
    ierr = KSPGetPC(dmmg[level]->ksp,&pc);CHKERRQ(ierr);
    if (ismg) {
      for (i=0; i<=level; i++) {
        ierr = PCMGGetSmoother(pc,i,&lksp);CHKERRQ(ierr); 
        ierr = KSPSetOperators(lksp,dmmg[i]->J,dmmg[i]->B,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
      }
    }
  }

  PetscFunctionReturn(0);
}