예제 #1
0
static PetscErrorCode TSStage_EIMEX(TS ts,PetscInt istage)
{
  TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
  PetscReal       h;
  Vec             Y=ext->Y, Z=ext->Z;
  SNES            snes;
  TSAdapt         adapt;
  PetscInt        i,its,lits;
  PetscBool       accept;
  PetscErrorCode  ierr;

  PetscFunctionBegin;
  ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
  h = ts->time_step/ext->N[istage];/* step size for the istage-th stage */
  ext->shift = 1./h;
  ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */
  ierr = VecCopy(ext->VecSolPrev,Y);CHKERRQ(ierr); /* Take the previous solution as intial step */

  for(i=0; i<ext->N[istage]; i++){
    ext->ctime = ts->ptime + h*i;
    ierr = VecCopy(Y,Z);CHKERRQ(ierr);/* Save the solution of the previous substep */
    ierr = SNESSolve(snes,NULL,Y);CHKERRQ(ierr);
    ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
    ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
    ts->snes_its += its; ts->ksp_its += lits;
    ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
    ierr = TSAdaptCheckStage(adapt,ts,ext->ctime,Y,&accept);CHKERRQ(ierr);
  }

  PetscFunctionReturn(0);
}
void VentilationProblem::SolveFromPressureWithSnes()
{
    assert( !mFluxGivenAtInflow );  // It's not a direct solve
    if (mTerminalInteractionMatrix == NULL)
    {
        SetupIterativeSolver();
    }

    SNES snes;
    SNESCreate(PETSC_COMM_SELF, &snes);

    // Set the residual creation function (direct solve flux->pressure followed by pressure matching)
    SNESSetFunction(snes, mTerminalPressureChangeVector /*residual*/ , &ComputeSnesResidual, this);
    // The approximate Jacobian has been precomputed so we are going to wing it
    SNESSetJacobian(snes, mTerminalInteractionMatrix, mTerminalInteractionMatrix, /*&ComputeSnesJacobian*/ NULL, this);
#if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x
    SNESSetLagJacobian(snes, -1 /*Never rebuild Jacobian*/);
#else
    SNESSetType(snes, SNESLS);
#endif

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 4) //PETSc 3.4 or later
    SNESSetType(snes, SNESNEWTONLS);
#else
    SNESSetType(snes, SNESLS);
#endif
    // Set the relative tolerance on the residual
    // Also set the absolute tolerance - useful for when the solver is started from the correct answer
    SNESSetTolerances(snes, 1.0e-16/*abs_tol*/, 1e-15/*r_tol*/, PETSC_DEFAULT/*step_tol*/, PETSC_DEFAULT, PETSC_DEFAULT);

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 3) //PETSc 3.3
    SNESLineSearch linesearch;
    SNESGetSNESLineSearch(snes, &linesearch);
    SNESLineSearchSetType(linesearch, "bt"); //Use backtracking search as default
#elif (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 4) //PETSc 3.4 or later
    SNESLineSearch linesearch;
    SNESGetLineSearch(snes, &linesearch);
    SNESLineSearchSetType(linesearch, "bt"); //Use backtracking search as default
#endif

    SNESSetFromOptions(snes);

#if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 5)
    // Seems to want the preconditioner to be explicitly set to none now
    // Copied this from the similar PETSc example at:
    // http://www.mcs.anl.gov/petsc/petsc-current/src/snes/examples/tutorials/ex1.c
    // Which got it to work...
    KSP ksp;
    SNESGetKSP(snes,&ksp);
    PC pc;
    KSPGetPC(ksp,&pc);
    PCSetType(pc,PCNONE);
#endif

#if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
    SNESSolve(snes, mTerminalFluxChangeVector);
#else
    SNESSolve(snes, PETSC_NULL, mTerminalFluxChangeVector);
#endif

    ///\todo #2300 If used with time-stepping we should maintain a permanent SNES object
    SNESDestroy(PETSC_DESTROY_PARAM(snes));

}