static PetscErrorCode SNESSetUp_QN(SNES snes) { SNES_QN *qn = (SNES_QN*)snes->data; PetscErrorCode ierr; PetscFunctionBegin; ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->U);CHKERRQ(ierr); ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->V);CHKERRQ(ierr); ierr = PetscMalloc3(qn->m, PetscScalar, &qn->alpha, qn->m, PetscScalar, &qn->beta, qn->m, PetscScalar, &qn->dXtdF);CHKERRQ(ierr); if (qn->singlereduction) { ierr = PetscMalloc3(qn->m*qn->m, PetscScalar, &qn->dXdFmat, qn->m, PetscScalar, &qn->dFtdX, qn->m, PetscScalar, &qn->YtdX);CHKERRQ(ierr); } ierr = SNESSetWorkVecs(snes,4);CHKERRQ(ierr); /* set up the line search */ if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); } if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) {snes->functype = SNES_FUNCTION_UNPRECONDITIONED;} PetscFunctionReturn(0); }
/*------------------------------------------------------------*/ static PetscErrorCode SNESSetUp_NEWTONTR(SNES snes) { PetscErrorCode ierr; PetscFunctionBegin; ierr = SNESSetWorkVecs(snes,3);CHKERRQ(ierr); ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SNESSetUp_NCG(SNES snes) { PetscErrorCode ierr; PetscFunctionBegin; ierr = SNESSetWorkVecs(snes,2);CHKERRQ(ierr); if (snes->pcside == PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNESNCG only supports left preconditioning"); if (snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_UNPRECONDITIONED; PetscFunctionReturn(0); }
static PetscErrorCode SNESSetUp_MS(SNES snes) { SNES_MS *ms = (SNES_MS*)snes->data; PetscErrorCode ierr; PetscFunctionBegin; if (!ms->tableau) {ierr = SNESMSSetType(snes,SNESMSDefault);CHKERRQ(ierr);} ierr = SNESSetWorkVecs(snes,3);CHKERRQ(ierr); ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode SNESSetUp_QN(SNES snes) { SNES_QN *qn = (SNES_QN*)snes->data; PetscErrorCode ierr; DM dm; PetscFunctionBegin; if (!snes->vec_sol) { ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr); } ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->U);CHKERRQ(ierr); if (qn->type != SNES_QN_BROYDEN) ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->V);CHKERRQ(ierr); ierr = PetscMalloc4(qn->m,&qn->alpha,qn->m,&qn->beta,qn->m,&qn->dXtdF,qn->m,&qn->lambda);CHKERRQ(ierr); if (qn->singlereduction) { ierr = PetscMalloc3(qn->m*qn->m,&qn->dXdFmat,qn->m,&qn->dFtdX,qn->m,&qn->YtdX);CHKERRQ(ierr); } ierr = SNESSetWorkVecs(snes,4);CHKERRQ(ierr); /* set method defaults */ if (qn->scale_type == SNES_QN_SCALE_DEFAULT) { if (qn->type == SNES_QN_BADBROYDEN) { qn->scale_type = SNES_QN_SCALE_NONE; } else { qn->scale_type = SNES_QN_SCALE_SHANNO; } } if (qn->restart_type == SNES_QN_RESTART_DEFAULT) { if (qn->type == SNES_QN_LBFGS) { qn->restart_type = SNES_QN_RESTART_POWELL; } else { qn->restart_type = SNES_QN_RESTART_PERIODIC; } } if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); } if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) {snes->functype = SNES_FUNCTION_UNPRECONDITIONED;} PetscFunctionReturn(0); }
PetscErrorCode SNESSetUp_VI(SNES snes) { PetscErrorCode ierr; PetscInt i_start[3],i_end[3]; PetscFunctionBegin; ierr = SNESSetWorkVecs(snes,1);CHKERRQ(ierr); ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); if (!snes->ops->computevariablebounds && snes->dm) { PetscBool flag; ierr = DMHasVariableBounds(snes->dm, &flag);CHKERRQ(ierr); snes->ops->computevariablebounds = SNESVIDMComputeVariableBounds; } if (!snes->usersetbounds) { if (snes->ops->computevariablebounds) { if (!snes->xl) {ierr = VecDuplicate(snes->vec_sol,&snes->xl);CHKERRQ(ierr);} if (!snes->xu) {ierr = VecDuplicate(snes->vec_sol,&snes->xu);CHKERRQ(ierr);} ierr = (*snes->ops->computevariablebounds)(snes,snes->xl,snes->xu);CHKERRQ(ierr); } else if (!snes->xl && !snes->xu) { /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ ierr = VecDuplicate(snes->vec_sol, &snes->xl);CHKERRQ(ierr); ierr = VecSet(snes->xl,SNES_VI_NINF);CHKERRQ(ierr); ierr = VecDuplicate(snes->vec_sol, &snes->xu);CHKERRQ(ierr); ierr = VecSet(snes->xu,SNES_VI_INF);CHKERRQ(ierr); } else { /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); ierr = VecGetOwnershipRange(snes->xl,i_start+1,i_end+1);CHKERRQ(ierr); ierr = VecGetOwnershipRange(snes->xu,i_start+2,i_end+2);CHKERRQ(ierr); if ((i_start[0] != i_start[1]) || (i_start[0] != i_start[2]) || (i_end[0] != i_end[1]) || (i_end[0] != i_end[2])) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Distribution of lower bound, upper bound and the solution vector should be identical across all the processors."); } } PetscFunctionReturn(0); }
PetscErrorCode SNESSetUp_FAS(SNES snes) { SNES_FAS *fas = (SNES_FAS*) snes->data; PetscErrorCode ierr; 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 = NULL; snes->vec_func = NULL; snes->vec_sol_update = NULL; snes->vec_rhs = NULL; /* reset the number of levels */ ierr = SNESFASSetLevels(snes,dm_levels,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! */ ierr = SNESSetWorkVecs(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, PetscObjectComm((PetscObject)next), &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, &fas->inject);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, NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); } if (fas->smoothd && fas->level != fas->levels - 1) { ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); } if (fas->smoothu && fas->level != fas->levels - 1) { ierr = SNESSetFunction(fas->smoothu, 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 = SNESSetNormSchedule(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); } else { ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); } ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); ierr = SNESGetLineSearch(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); fas->smoothd->vec_sol = snes->vec_sol; ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); fas->smoothd->vec_sol_update = snes->vec_sol_update; ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); fas->smoothd->vec_func = snes->vec_func; ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);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 = SNESSetNormSchedule(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); } else { ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); } ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); ierr = SNESGetLineSearch(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); fas->smoothu->vec_sol = snes->vec_sol; ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); fas->smoothu->vec_sol_update = snes->vec_sol_update; ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); fas->smoothu->vec_func = snes->vec_func; ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);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 = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); ierr = SNESGetLineSearch(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); }
PetscErrorCode SNESSolve_Composite(SNES snes) { Vec F; Vec X; Vec B; PetscInt i; PetscReal fnorm = 0.0, xnorm = 0.0, snorm = 0.0; PetscErrorCode ierr; SNESNormSchedule normtype; SNES_Composite *comp = (SNES_Composite*)snes->data; PetscFunctionBegin; X = snes->vec_sol; F = snes->vec_func; B = snes->vec_rhs; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; comp->innerFailures = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESSetWorkVecs(snes, 1);CHKERRQ(ierr); snes->reason = SNES_CONVERGED_ITERATING; ierr = SNESGetNormSchedule(snes, &normtype);CHKERRQ(ierr); if (normtype == SNES_NORM_ALWAYS || normtype == SNES_NORM_INITIAL_ONLY || normtype == SNES_NORM_INITIAL_FINAL_ONLY) { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ } SNESCheckFunctionNorm(snes,fnorm); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } else { ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } for (i = 0; i < snes->max_its; i++) { /* Copy the state before modification by application of the composite solver; we will subtract the new state after application */ ierr = VecCopy(X, snes->work[0]);CHKERRQ(ierr); if (comp->type == SNES_COMPOSITE_ADDITIVE) { ierr = SNESCompositeApply_Additive(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_MULTIPLICATIVE) { ierr = SNESCompositeApply_Multiplicative(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_ADDITIVEOPTIMAL) { ierr = SNESCompositeApply_AdditiveOptimal(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported SNESComposite type"); if (snes->reason < 0) break; /* Compute the solution update for convergence testing */ ierr = VecAXPY(snes->work[0], -1.0, X);CHKERRQ(ierr); ierr = VecScale(snes->work[0], -1.0);CHKERRQ(ierr); if ((i == snes->max_its - 1) && (normtype == SNES_NORM_INITIAL_FINAL_ONLY || normtype == SNES_NORM_FINAL_ONLY)) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->xl && snes->xu) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } else { ierr = VecNormBegin(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,fnorm); } else if (normtype == SNES_NORM_ALWAYS) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ if (normtype == SNES_NORM_ALWAYS) {ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,snorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);} if (snes->reason) break; /* Call general purpose update function */ if (snes->ops->update) {ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);} } if (normtype == SNES_NORM_ALWAYS) { if (i == snes->max_its) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",snes->max_its);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode SNESComputeNGSDefaultSecant(SNES snes,Vec X,Vec B,void *ctx) { PetscErrorCode ierr; SNES_NGS *gs = (SNES_NGS*)snes->data; PetscInt i,j,k,ncolors; DM dm; PetscBool flg; ISColoring coloring = gs->coloring; MatColoring mc; Vec W,G,F; PetscScalar h=gs->h; IS *coloris; PetscScalar f,g,x,w,d; PetscReal dxt,xt,ft,ft1=0; const PetscInt *idx; PetscInt size,s; PetscReal atol,rtol,stol; PetscInt its; PetscErrorCode (*func)(SNES,Vec,Vec,void*); void *fctx; PetscBool mat = gs->secant_mat,equal,isdone,alldone; PetscScalar *xa,*fa,*wa,*ga; PetscFunctionBegin; if (snes->nwork < 3) { ierr = SNESSetWorkVecs(snes,3);CHKERRQ(ierr); } W = snes->work[0]; G = snes->work[1]; F = snes->work[2]; ierr = VecGetOwnershipRange(X,&s,NULL);CHKERRQ(ierr); ierr = SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its);CHKERRQ(ierr); ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,&func,&fctx);CHKERRQ(ierr); if (!coloring) { /* create the coloring */ ierr = DMHasColoring(dm,&flg);CHKERRQ(ierr); if (flg && !mat) { ierr = DMCreateColoring(dm,IS_COLORING_GLOBAL,&coloring);CHKERRQ(ierr); } else { if (!snes->jacobian) {ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);} ierr = MatColoringCreate(snes->jacobian,&mc);CHKERRQ(ierr); ierr = MatColoringSetDistance(mc,1);CHKERRQ(ierr); ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr); ierr = MatColoringApply(mc,&coloring);CHKERRQ(ierr); ierr = MatColoringDestroy(&mc);CHKERRQ(ierr); } gs->coloring = coloring; } ierr = ISColoringGetIS(coloring,&ncolors,&coloris);CHKERRQ(ierr); ierr = VecEqual(X,snes->vec_sol,&equal);CHKERRQ(ierr); if (equal && snes->normschedule == SNES_NORM_ALWAYS) { /* assume that the function is already computed */ ierr = VecCopy(snes->vec_func,F);CHKERRQ(ierr); } else { ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,X,F,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(F,-1.0,B);CHKERRQ(ierr);} } ierr = VecGetArray(X,&xa);CHKERRQ(ierr); ierr = VecGetArray(F,&fa);CHKERRQ(ierr); ierr = VecGetArray(G,&ga);CHKERRQ(ierr); ierr = VecGetArray(W,&wa);CHKERRQ(ierr); for (i=0;i<ncolors;i++) { ierr = ISGetIndices(coloris[i],&idx);CHKERRQ(ierr); ierr = ISGetLocalSize(coloris[i],&size);CHKERRQ(ierr); ierr = VecCopy(X,W);CHKERRQ(ierr); for (j=0;j<size;j++) { wa[idx[j]-s] += h; } ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,W,G,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(G,-1.0,B);CHKERRQ(ierr);} for (k=0;k<its;k++) { dxt = 0.; xt = 0.; ft = 0.; for (j=0;j<size;j++) { f = fa[idx[j]-s]; x = xa[idx[j]-s]; g = ga[idx[j]-s]; w = wa[idx[j]-s]; if (PetscAbsScalar(g-f) > atol) { /* This is equivalent to d = x - (h*f) / PetscRealPart(g-f) */ d = (x*g-w*f) / PetscRealPart(g-f); } else { d = x; } dxt += PetscRealPart(PetscSqr(d-x)); xt += PetscRealPart(PetscSqr(x)); ft += PetscRealPart(PetscSqr(f)); xa[idx[j]-s] = d; } if (k == 0) ft1 = PetscSqrtReal(ft); if (k<its-1) { isdone = PETSC_FALSE; if (stol*PetscSqrtReal(xt) > PetscSqrtReal(dxt)) isdone = PETSC_TRUE; if (PetscSqrtReal(ft) < atol) isdone = PETSC_TRUE; if (rtol*ft1 > PetscSqrtReal(ft)) isdone = PETSC_TRUE; ierr = MPIU_Allreduce(&isdone,&alldone,1,MPIU_BOOL,MPI_BAND,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); if (alldone) break; } if (i < ncolors-1 || k < its-1) { ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,X,F,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(F,-1.0,B);CHKERRQ(ierr);} } if (k<its-1) { ierr = VecSwap(X,W);CHKERRQ(ierr); ierr = VecSwap(F,G);CHKERRQ(ierr); } } } ierr = VecRestoreArray(X,&xa);CHKERRQ(ierr); ierr = VecRestoreArray(F,&fa);CHKERRQ(ierr); ierr = VecRestoreArray(G,&ga);CHKERRQ(ierr); ierr = VecRestoreArray(W,&wa);CHKERRQ(ierr); ierr = ISColoringRestoreIS(coloring,&coloris);CHKERRQ(ierr); PetscFunctionReturn(0); }