PetscErrorCode SNESFASCycle_Full(SNES snes, Vec X) { PetscErrorCode ierr; Vec F,B; SNES_FAS *fas = (SNES_FAS*)snes->data; PetscBool isFine; SNES next; PetscFunctionBegin; F = snes->vec_func; B = snes->vec_rhs; ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); if (isFine) { ierr = SNESFASCycleSetupPhase_Full(snes);CHKERRQ(ierr); } if (fas->full_stage == 0) { /* downsweep */ if (next) { if (fas->level != 1) next->max_its += 1; if (fas->full_downsweep||isFine) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); if (fas->level != 1) next->max_its -= 1; } else { /* The smoother on the coarse level is the coarse solver */ ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); } fas->full_stage = 1; } else if (fas->full_stage == 1) { if (snes->iter == 0) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} if (next) { ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); } } /* final v-cycle */ if (isFine) { if (next) { ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
PetscErrorCode SNESFASCycle_Kaskade(SNES snes, Vec X) { PetscErrorCode ierr; Vec F,B; SNES next; PetscFunctionBegin; F = snes->vec_func; B = snes->vec_rhs; ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); if (next) { ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); } else { ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* Defines the FAS cycle as: fine problem: F(x) = 0 coarse problem: F^c(x) = b^c b^c = F^c(I^c_fx^f - I^c_fF(x)) correction: x = x + I(x^c - Rx) */ PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) { PetscErrorCode ierr; Vec F,B; SNES_FAS *fas = (SNES_FAS *)snes->data; PetscFunctionBegin; F = snes->vec_func; B = snes->vec_rhs; /* pre-smooth -- just update using the pre-smoother */ ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); if (fas->level != 0) { ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* The additive cycle looks like: xhat = x xhat = dS(x, b) x = coarsecorrection(xhat, b_d) x = x + nu*(xhat - x); (optional) x = uS(x, b) With the coarse RHS (defect correction) as below. */ PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) { Vec F, B, Xhat; Vec X_c, Xo_c, F_c, B_c; PetscErrorCode ierr; SNESConvergedReason reason; PetscReal xnorm, fnorm, ynorm; PetscBool lssuccess; SNES next; Mat restrct, interpolate; SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; PetscFunctionBegin; ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); F = snes->vec_func; B = snes->vec_rhs; Xhat = snes->work[1]; ierr = VecCopy(X, Xhat);CHKERRQ(ierr); /* recurse first */ if (next) { fasc = (SNES_FAS*)next->data; ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); X_c = next->vec_sol; Xo_c = next->work[0]; F_c = next->vec_func; B_c = next->vec_rhs; ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); /* restrict the defect */ ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); /* set initial guess of the coarse problem to the projected fine solution */ ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); /* recurse */ ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); /* smooth on this level */ ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } /* correct as x <- x + I(x^c - Rx)*/ ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); /* additive correction of the coarse direction*/ ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssuccess);CHKERRQ(ierr); if (!lssuccess) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; PetscFunctionReturn(0); } } ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); } else { ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); } PetscFunctionReturn(0); }