Exemplo n.º 1
0
static PetscErrorCode SNESSetFromOptions_QN(SNES snes)
{

  PetscErrorCode    ierr;
  SNES_QN           *qn = (SNES_QN*)snes->data;
  PetscBool         monflg = PETSC_FALSE,flg;
  SNESLineSearch    linesearch;
  SNESQNRestartType rtype = qn->restart_type;
  SNESQNScaleType   stype = qn->scale_type;

  PetscFunctionBegin;
  ierr = PetscOptionsHead("SNES QN options");CHKERRQ(ierr);
  ierr = PetscOptionsInt("-snes_qn_m","Number of past states saved for L-BFGS methods","SNESQN",qn->m,&qn->m,PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsReal("-snes_qn_powell_gamma","Powell angle tolerance",          "SNESQN", qn->powell_gamma, &qn->powell_gamma, PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsReal("-snes_qn_powell_downhill","Powell descent tolerance",        "SNESQN", qn->powell_downhill, &qn->powell_downhill, PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsBool("-snes_qn_monitor",         "Monitor for the QN methods",      "SNESQN", monflg, &monflg, PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsBool("-snes_qn_single_reduction", "Aggregate reductions",           "SNESQN", qn->singlereduction, &qn->singlereduction, PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsEnum("-snes_qn_scale_type","Scaling type","SNESQNSetScaleType",SNESQNScaleTypes,(PetscEnum)stype,(PetscEnum*)&stype,&flg);CHKERRQ(ierr);
  if (flg) ierr = SNESQNSetScaleType(snes,stype);CHKERRQ(ierr);

  ierr = PetscOptionsEnum("-snes_qn_restart_type","Restart type","SNESQNSetRestartType",SNESQNRestartTypes,(PetscEnum)rtype,(PetscEnum*)&rtype,&flg);CHKERRQ(ierr);
  if (flg) ierr = SNESQNSetRestartType(snes,rtype);CHKERRQ(ierr);

  ierr = PetscOptionsEnum("-snes_qn_type","Quasi-Newton update type","",SNESQNTypes,
                          (PetscEnum)qn->type,(PetscEnum*)&qn->type,PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsTail();CHKERRQ(ierr);
  if (!snes->linesearch) {
    ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
  }
  if (monflg) {
    qn->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Exemplo n.º 2
0
PetscErrorCode SNESSetUp_VINEWTONRSLS(SNES snes)
{
  PetscErrorCode    ierr;
  SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*) snes->data;
  PetscInt          *indices;
  PetscInt          i,n,rstart,rend;
  SNESLineSearch    linesearch;

  PetscFunctionBegin;
  ierr = SNESSetUp_VI(snes);CHKERRQ(ierr);

  /* Set up previous active index set for the first snes solve
   vi->IS_inact_prev = 0,1,2,....N */

  ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
  ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
  ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
  for (i=0;i < n; i++) indices[i] = rstart + i;
  ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);CHKERRQ(ierr);

  /* set the line search functions */
  if (!snes->linesearch) {
    ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Exemplo n.º 3
0
static PetscErrorCode SNESSetFromOptions_NRichardson(SNES snes)
{
  PetscErrorCode ierr;
  SNESLineSearch linesearch;

  PetscFunctionBegin;
  ierr = PetscOptionsHead("SNES Richardson options");CHKERRQ(ierr);
  ierr = PetscOptionsTail();CHKERRQ(ierr);
  if (!snes->linesearch) {
    ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Exemplo n.º 4
0
static PetscErrorCode SNESSetFromOptions_NEWTONLS(SNES snes)
{
  PetscErrorCode ierr;
  SNESLineSearch linesearch;

  PetscFunctionBegin;
  ierr = PetscOptionsHead("SNESNEWTONLS options");CHKERRQ(ierr);
  ierr = PetscOptionsTail();CHKERRQ(ierr);
  /* set the default line search type */
  if (!snes->linesearch) {
    ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Exemplo n.º 5
0
PetscErrorCode SNESSetFromOptions_VI(SNES snes)
{
  PetscErrorCode ierr;
  PetscBool      flg;
  SNESLineSearch linesearch;

  PetscFunctionBegin;
  ierr = PetscOptionsHead("SNES VI options");CHKERRQ(ierr);
  ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
  if (flg) {
    ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
  }
  if (!snes->linesearch) {
    ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
    ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr);
  }
  ierr = PetscOptionsTail();CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
Exemplo n.º 6
0
void petscSetupDampers(NonlinearImplicitSystem& sys)
{
  FEProblem * problem = sys.get_equation_systems().parameters.get<FEProblem *>("_fe_problem");
  NonlinearSystem & nl = problem->getNonlinearSystem();
  PetscNonlinearSolver<Number> * petsc_solver = dynamic_cast<PetscNonlinearSolver<Number> *>(nl.sys().nonlinear_solver.get());
  SNES snes = petsc_solver->snes();

#if PETSC_VERSION_LESS_THAN(3,3,0)
  // PETSc 3.2.x-
  SNESLineSearchSetPostCheck(snes, dampedCheck, problem);
#else
  // PETSc 3.3.0+
  SNESLineSearch linesearch;
#if PETSC_VERSION_LESS_THAN(3,4,0)
  PetscErrorCode ierr = SNESGetSNESLineSearch(snes, &linesearch);
#else
  PetscErrorCode ierr = SNESGetLineSearch(snes, &linesearch);
#endif
  CHKERRABORT(problem->comm().get(),ierr);

  ierr = SNESLineSearchSetPostCheck(linesearch, dampedCheck, problem);
  CHKERRABORT(problem->comm().get(),ierr);
#endif
}
Exemplo n.º 7
0
static PetscErrorCode SNESSetFromOptions_NCG(SNES snes)
{
    SNES_NCG           *ncg     = (SNES_NCG *)snes->data;
    PetscErrorCode     ierr;
    PetscBool          debug;
    SNESLineSearch     linesearch;
    SNESNCGType        ncgtype=ncg->type;

    PetscFunctionBegin;
    ierr = PetscOptionsHead("SNES NCG options");
    CHKERRQ(ierr);
    ierr = PetscOptionsBool("-snes_ncg_monitor","Monitor NCG iterations","SNES",ncg->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);
    CHKERRQ(ierr);
    ierr = PetscOptionsEnum("-snes_ncg_type","NCG Beta type used","SNESNCGSetType",SNESNCGTypes,(PetscEnum)ncg->type,(PetscEnum*)&ncgtype,PETSC_NULL);
    CHKERRQ(ierr);
    ierr = SNESNCGSetType(snes, ncgtype);
    CHKERRQ(ierr);
    if (debug) {
        ncg->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);
        CHKERRQ(ierr);
    }
    ierr = PetscOptionsTail();
    CHKERRQ(ierr);
    if (!snes->linesearch) {
        ierr = SNESGetSNESLineSearch(snes, &linesearch);
        CHKERRQ(ierr);
        if (!snes->pc) {
            ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);
            CHKERRQ(ierr);
        } else {
            ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);
            CHKERRQ(ierr);
        }
    }
    PetscFunctionReturn(0);
}
Exemplo n.º 8
0
EXTERN_C_END

/*
  SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method.

  Input Parameters:
. snes - the SNES context

  Output Parameter:
. outits - number of iterations until termination

  Application Interface Routine: SNESSolve()
*/
#undef __FUNCT__
#define __FUNCT__ "SNESSolve_NCG"
PetscErrorCode SNESSolve_NCG(SNES snes)
{
    SNES_NCG            *ncg = (SNES_NCG *)snes->data;
    Vec                 X, dX, lX, F, B, Fold;
    PetscReal           fnorm, ynorm, xnorm, beta = 0.0;
    PetscScalar         dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold;
    PetscInt            maxits, i;
    PetscErrorCode      ierr;
    SNESConvergedReason reason;
    PetscBool           lsSuccess = PETSC_TRUE;
    SNESLineSearch     linesearch;

    PetscFunctionBegin;
    snes->reason = SNES_CONVERGED_ITERATING;

    maxits = snes->max_its;            /* maximum number of iterations */
    X      = snes->vec_sol;            /* X^n */
    Fold   = snes->work[0];            /* The previous iterate of X */
    dX     = snes->work[1];            /* the preconditioned direction */
    lX     = snes->vec_sol_update;     /* the conjugate direction */
    F      = snes->vec_func;           /* residual vector */
    B      = snes->vec_rhs;            /* the right hand side */

    ierr = SNESGetSNESLineSearch(snes, &linesearch);
    CHKERRQ(ierr);

    ierr = PetscObjectTakeAccess(snes);
    CHKERRQ(ierr);
    snes->iter = 0;
    snes->norm = 0.;
    ierr = PetscObjectGrantAccess(snes);
    CHKERRQ(ierr);

    /* compute the initial function and preconditioned update dX */
    if (!snes->vec_func_init_set) {
        ierr = SNESComputeFunction(snes,X,F);
        CHKERRQ(ierr);
        if (snes->domainerror) {
            snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
            PetscFunctionReturn(0);
        }
    } else {
        snes->vec_func_init_set = PETSC_FALSE;
    }
    if (!snes->norm_init_set) {
        /* convergence test */
        ierr = VecNorm(F, NORM_2, &fnorm);
        CHKERRQ(ierr); /* fnorm <- ||F||  */
        if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
    } else {
        fnorm = snes->norm_init;
        snes->norm_init_set = PETSC_FALSE;
    }
    ierr = PetscObjectTakeAccess(snes);
    CHKERRQ(ierr);
    snes->norm = fnorm;
    ierr = PetscObjectGrantAccess(snes);
    CHKERRQ(ierr);
    SNESLogConvHistory(snes,fnorm,0);
    ierr = SNESMonitor(snes,0,fnorm);
    CHKERRQ(ierr);

    /* set parameter for default relative tolerance convergence test */
    snes->ttol = fnorm*snes->rtol;
    /* test convergence */
    ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);
    CHKERRQ(ierr);
    if (snes->reason) PetscFunctionReturn(0);

    /* Call general purpose update function */
    if (snes->ops->update) {
        ierr = (*snes->ops->update)(snes, snes->iter);
        CHKERRQ(ierr);
    }

    /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */

    if (snes->pc && snes->pcside == PC_RIGHT) {
        ierr = VecCopy(X, dX);
        CHKERRQ(ierr);
        ierr = SNESSetInitialFunction(snes->pc, F);
        CHKERRQ(ierr);
        ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);
        CHKERRQ(ierr);
        ierr = SNESSolve(snes->pc, B, dX);
        CHKERRQ(ierr);
        ierr = SNESGetConvergedReason(snes->pc,&reason);
        CHKERRQ(ierr);
        if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
            snes->reason = SNES_DIVERGED_INNER;
            PetscFunctionReturn(0);
        }
        ierr = VecAYPX(dX,-1.0,X);
        CHKERRQ(ierr);
    } else {
        ierr = VecCopy(F, dX);
        CHKERRQ(ierr);
    }
    ierr = VecCopy(dX, lX);
    CHKERRQ(ierr);
    ierr = VecDot(F, dX, &dXdotF);
    CHKERRQ(ierr);
    /*
    } else {
      ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr);
    }
     */
    for (i = 1; i < maxits + 1; i++) {
        lsSuccess = PETSC_TRUE;
        /* some update types require the old update direction or conjugate direction */
        if (ncg->type != SNES_NCG_FR) {
            ierr = VecCopy(F, Fold);
            CHKERRQ(ierr);
        }
        ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX);
        CHKERRQ(ierr);
        ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);
        CHKERRQ(ierr);
        if (!lsSuccess) {
            if (++snes->numFailures >= snes->maxFailures) {
                snes->reason = SNES_DIVERGED_LINE_SEARCH;
                PetscFunctionReturn(0);
            }
        }
        if (snes->nfuncs >= snes->max_funcs) {
            snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
            PetscFunctionReturn(0);
        }
        if (snes->domainerror) {
            snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
            PetscFunctionReturn(0);
        }
        ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);
        CHKERRQ(ierr);
        /* Monitor convergence */
        ierr = PetscObjectTakeAccess(snes);
        CHKERRQ(ierr);
        snes->iter = i;
        snes->norm = fnorm;
        ierr = PetscObjectGrantAccess(snes);
        CHKERRQ(ierr);
        SNESLogConvHistory(snes,snes->norm,0);
        ierr = SNESMonitor(snes,snes->iter,snes->norm);
        CHKERRQ(ierr);

        /* Test for convergence */
        ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);
        CHKERRQ(ierr);
        if (snes->reason) PetscFunctionReturn(0);

        /* Call general purpose update function */
        if (snes->ops->update) {
            ierr = (*snes->ops->update)(snes, snes->iter);
            CHKERRQ(ierr);
        }
        if (snes->pc && snes->pcside == PC_RIGHT) {
            ierr = VecCopy(X,dX);
            CHKERRQ(ierr);
            ierr = SNESSetInitialFunction(snes->pc, F);
            CHKERRQ(ierr);
            ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);
            CHKERRQ(ierr);
            ierr = SNESSolve(snes->pc, B, dX);
            CHKERRQ(ierr);
            ierr = SNESGetConvergedReason(snes->pc,&reason);
            CHKERRQ(ierr);
            if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
                snes->reason = SNES_DIVERGED_INNER;
                PetscFunctionReturn(0);
            }
            ierr = VecAYPX(dX,-1.0,X);
            CHKERRQ(ierr);
        } else {
            ierr = VecCopy(F, dX);
            CHKERRQ(ierr);
        }

        /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/
        switch(ncg->type) {
        case SNES_NCG_FR: /* Fletcher-Reeves */
            dXolddotFold = dXdotF;
            ierr = VecDot(dX, dX, &dXdotF);
            CHKERRQ(ierr);
            beta = PetscRealPart(dXdotF / dXolddotFold);
            break;
        case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */
            dXolddotFold = dXdotF;
            ierr = VecDotBegin(F, dX, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(Fold, dX, &dXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotEnd(F, dX, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(Fold, dX, &dXdotFold);
            CHKERRQ(ierr);
            beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold));
            if (beta < 0.0) beta = 0.0; /* restart */
            break;
        case SNES_NCG_HS: /* Hestenes-Stiefel */
            ierr = VecDotBegin(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(dX, Fold, &dXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotBegin(lX, F, &lXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotEnd(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(dX, Fold, &dXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotEnd(lX, F, &lXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold));
            break;
        case SNES_NCG_DY: /* Dai-Yuan */
            ierr = VecDotBegin(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(lX, F, &lXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotEnd(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(lX, F, &lXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));
            CHKERRQ(ierr);
            break;
        case SNES_NCG_CD: /* Conjugate Descent */
            ierr = VecDotBegin(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotBegin(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            ierr = VecDotEnd(dX, F, &dXdotF);
            CHKERRQ(ierr);
            ierr = VecDotEnd(lX, Fold, &lXdotFold);
            CHKERRQ(ierr);
            beta = PetscRealPart(dXdotF / lXdotFold);
            CHKERRQ(ierr);
            break;
        }
        if (ncg->monitor) {
            ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);
            CHKERRQ(ierr);
        }
        ierr = VecAYPX(lX, beta, dX);
        CHKERRQ(ierr);
    }
    ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);
    CHKERRQ(ierr);
    if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
    PetscFunctionReturn(0);
}
Exemplo n.º 9
0
PetscErrorCode SNESSolve_NEWTONLS(SNES snes)
{
  PetscErrorCode      ierr;
  PetscInt            maxits,i,lits;
  PetscBool           lssucceed;
  MatStructure        flg = DIFFERENT_NONZERO_PATTERN;
  PetscReal           fnorm,gnorm,xnorm,ynorm;
  Vec                 Y,X,F,G,W,FPC;
  KSPConvergedReason  kspreason;
  PetscBool           domainerror;
  SNESLineSearch      linesearch;
  SNESConvergedReason reason;

  PetscFunctionBegin;
  snes->numFailures            = 0;
  snes->numLinearSolveFailures = 0;
  snes->reason                 = SNES_CONVERGED_ITERATING;

  maxits        = snes->max_its;        /* maximum number of iterations */
  X             = snes->vec_sol;        /* solution vector */
  F             = snes->vec_func;       /* residual vector */
  Y             = snes->vec_sol_update; /* newton step */
  G             = snes->work[0];
  W             = snes->work[1];

  ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
  snes->iter = 0;
  snes->norm = 0.0;
  ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
  ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
  if (!snes->vec_func_init_set) {
    ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
    ierr = SNESGetFunctionDomainError(snes, &domainerror);CHKERRQ(ierr);
    if (domainerror) {
      snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
      PetscFunctionReturn(0);
    }
  } else {
    snes->vec_func_init_set = PETSC_FALSE;
  }
  if (!snes->norm_init_set) {
    ierr = VecNormBegin(F,NORM_2,&fnorm);CHKERRQ(ierr);        /* fnorm <- ||F||  */
    ierr = VecNormEnd(F,NORM_2,&fnorm);CHKERRQ(ierr);
    if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
  } else {
    fnorm = snes->norm_init;
    snes->norm_init_set = PETSC_FALSE;
  }
  ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
  snes->norm = fnorm;
  ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
  SNESLogConvHistory(snes,fnorm,0);
  ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);

  /* set parameter for default relative tolerance convergence test */
  snes->ttol = fnorm*snes->rtol;
  /* test convergence */
  ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
  if (snes->reason) PetscFunctionReturn(0);

  for (i=0; i<maxits; i++) {

    /* Call general purpose update function */
    if (snes->ops->update) {
      ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
    }

    /* apply the nonlinear preconditioner if it's right preconditioned */
    if (snes->pc && snes->pcside == PC_RIGHT) {
      ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
      ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
      ierr = SNESSolve(snes->pc, snes->vec_rhs, X);CHKERRQ(ierr);
      ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
      if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
        snes->reason = SNES_DIVERGED_INNER;
        PetscFunctionReturn(0);
      }
      ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
      ierr = VecCopy(FPC, F);CHKERRQ(ierr);
      ierr = SNESGetFunctionNorm(snes->pc, &fnorm);CHKERRQ(ierr);
    }

    /* Solve J Y = F, where J is Jacobian matrix */
    ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
    ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
    ierr = SNES_KSPSolve(snes,snes->ksp,F,Y);CHKERRQ(ierr);
    ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
    if (kspreason < 0) {
      if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
        ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
        snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
        break;
      }
    }
    ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
    snes->linear_its += lits;
    ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);

    if (PetscLogPrintInfo){
      ierr = SNESNEWTONLSCheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
    }

    /* Compute a (scaled) negative update in the line search routine:
         X <- X - lambda*Y
       and evaluate F = function(X) (depends on the line search).
    */
    gnorm = fnorm;
    ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, Y);CHKERRQ(ierr);
    ierr = SNESLineSearchGetSuccess(linesearch, &lssucceed);CHKERRQ(ierr);
    ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
    ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)gnorm,(double)fnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
    if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
    ierr = SNESGetFunctionDomainError(snes, &domainerror);CHKERRQ(ierr);
    if (domainerror) {
      snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
      PetscFunctionReturn(0);
    }
    if (!lssucceed) {
      if (snes->stol*xnorm > ynorm) {
        snes->reason = SNES_CONVERGED_SNORM_RELATIVE;
        PetscFunctionReturn(0);
      }
      if (++snes->numFailures >= snes->maxFailures) {
        PetscBool  ismin;
        snes->reason = SNES_DIVERGED_LINE_SEARCH;
        ierr = SNESNEWTONLSCheckLocalMin_Private(snes,snes->jacobian,F,W,fnorm,&ismin);CHKERRQ(ierr);
        if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
        break;
      }
    }
    /* Monitor convergence */
    ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
    snes->iter = i+1;
    snes->norm = fnorm;
    ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
    SNESLogConvHistory(snes,snes->norm,lits);
    ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
    /* Test for convergence */
    ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
    if (snes->reason) break;
  }
  if (i == maxits) {
    ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
    if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
  }
  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));

}
Exemplo n.º 11
0
PetscErrorCode SNESSetFromOptions_FAS(SNES snes)
{
  SNES_FAS       *fas = (SNES_FAS *) snes->data;
  PetscInt       levels = 1;
  PetscBool      flg = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE;
  PetscErrorCode ierr;
  char           monfilename[PETSC_MAX_PATH_LEN];
  SNESFASType    fastype;
  const char     *optionsprefix;
  SNESLineSearch linesearch;
  PetscInt       m, n_up, n_down;
  SNES           next;
  PetscBool      isFine;

  PetscFunctionBegin;
  ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
  ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr);

  /* number of levels -- only process most options on the finest level */
  if (isFine) {
    ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr);
    if (!flg && snes->dm) {
      ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr);
      levels++;
      fas->usedmfornumberoflevels = PETSC_TRUE;
    }
    ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr);
    fastype = fas->fastype;
    ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr);
    if (flg) {
      ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr);
    }

    ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
    ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr);
    if (flg) {
      ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr);
    }

    ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr);
    if (flg) {
      ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr);
    }

    ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr);

    ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr);

    ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESFASSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr);
    if (monflg) ierr = SNESFASSetMonitor(snes, PETSC_TRUE);CHKERRQ(ierr);
  }

  ierr = PetscOptionsTail();CHKERRQ(ierr);
  /* setup from the determined types if there is no pointwise procedure or smoother defined */
  if (upflg) {
    ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr);
  }
  if (downflg) {
    ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr);
  }

  /* set up the default line search for coarse grid corrections */
  if (fas->fastype == SNES_FAS_ADDITIVE) {
    if (!snes->linesearch) {
      ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
      ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
    }
  }

  ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
  /* recursive option setting for the smoothers */
  if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);}
  PetscFunctionReturn(0);
}
Exemplo n.º 12
0
PetscErrorCode SNESSetUp_FAS(SNES snes)
{
  SNES_FAS       *fas = (SNES_FAS *) snes->data;
  PetscErrorCode ierr;
  VecScatter     injscatter;
  PetscInt       dm_levels;
  Vec            vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */
  SNES           next;
  PetscBool      isFine;
  SNESLineSearch linesearch;
  SNESLineSearch slinesearch;
  void           *lsprectx,*lspostctx;
  PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*);
  PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool *,PetscBool *,void*);

  PetscFunctionBegin;
  ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
  if (fas->usedmfornumberoflevels && isFine) {
    ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr);
    dm_levels++;
    if (dm_levels > fas->levels) {
      /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/
      vec_sol = snes->vec_sol;
      vec_func = snes->vec_func;
      vec_sol_update = snes->vec_sol_update;
      vec_rhs = snes->vec_rhs;
      snes->vec_sol = PETSC_NULL;
      snes->vec_func = PETSC_NULL;
      snes->vec_sol_update = PETSC_NULL;
      snes->vec_rhs = PETSC_NULL;

      /* reset the number of levels */
      ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr);
      ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);

      snes->vec_sol = vec_sol;
      snes->vec_func = vec_func;
      snes->vec_rhs = vec_rhs;
      snes->vec_sol_update = vec_sol_update;
    }
  }
  ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
  if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */

  if (fas->fastype == SNES_FAS_MULTIPLICATIVE) {
    ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */
  } else {
    ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */
  }

  /* set up the smoothers if they haven't already been set up */
  if (!fas->smoothd) {
    ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr);
  }

  if (snes->dm) {
    /* set the smoother DMs properly */
    if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr);
    ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr);
    /* construct EVERYTHING from the DM -- including the progressive set of smoothers */
    if (next) {
      /* for now -- assume the DM and the evaluation functions have been set externally */
      if (!next->dm) {
        ierr = DMCoarsen(snes->dm, ((PetscObject)next)->comm, &next->dm);CHKERRQ(ierr);
        ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr);
      }
      /* set the interpolation and restriction from the DM */
      if (!fas->interpolate) {
        ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr);
        if (!fas->restrct) {
          ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr);
          fas->restrct = fas->interpolate;
        }
      }
      /* set the injection from the DM */
      if (!fas->inject) {
        ierr = DMCreateInjection(next->dm, snes->dm, &injscatter);CHKERRQ(ierr);
        ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr);
        ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr);
      }
    }
  }
  /*pass the smoother, function, and jacobian up to the next level if it's not user set already */
  if (fas->galerkin) {
    if (next)
      ierr = SNESSetFunction(next, PETSC_NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr);
    if (fas->smoothd && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothd, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr);
    if (fas->smoothu && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothu, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr);
  }

  /* sets the down (pre) smoother's default norm and sets it from options */
  if (fas->smoothd){
    if (fas->level == 0 && fas->levels != 1) {
      ierr = SNESSetNormType(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr);
     } else {
      ierr = SNESSetNormType(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr);
    }
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr);
    ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
  }

  /* sets the up (post) smoother's default norm and sets it from options */
  if (fas->smoothu){
    if (fas->level != fas->levels - 1) {
      ierr = SNESSetNormType(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr);
    } else {
      ierr = SNESSetNormType(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr);
    }
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr);
    ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
  }

  if (next) {
    /* gotta set up the solution vector for this to work */
    if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);}
    if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);}
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr);
    ierr = SNESGetSNESLineSearch(fas->next,&slinesearch);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
    ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
    ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
    ierr = SNESSetUp(next);CHKERRQ(ierr);
  }
  /* setup FAS work vectors */
  if (fas->galerkin) {
    ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr);
    ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}