/* Defines the action of the downsmoother */ PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) { PetscErrorCode ierr = 0; SNESConvergedReason reason; Vec FPC; SNES smoothd; SNES_FAS *fas = (SNES_FAS*) snes->data; PetscFunctionBegin; ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} /* check convergence reason for the smoother */ ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} PetscFunctionReturn(0); }
/* Defines the action of the downsmoother */ PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) { PetscErrorCode ierr = 0; SNESConvergedReason reason; Vec FPC; SNES smoothd; PetscFunctionBegin; ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(smoothd, *fnorm);CHKERRQ(ierr); ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); /* check convergence reason for the smoother */ ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(smoothd, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(smoothd, fnorm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) { SNES_FAS *fas = (SNES_FAS*) snes->data; PetscBool isFine,iascii,isdraw; PetscInt i; PetscErrorCode ierr; SNES smoothu, smoothd, levelsnes; PetscFunctionBegin; ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); if (isFine) { ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); if (iascii) { ierr = PetscViewerASCIIPrintf(viewer, "FAS: type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); if (fas->galerkin) { ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); } for (i=0; i<fas->levels; i++) { ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); if (!i) { ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); } ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); if (smoothd) { ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); } ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); if (i && (smoothd == smoothu)) { ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); } else if (i) { ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); if (smoothu) { ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); } ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); } } } else if (isdraw) { PetscDraw draw; PetscReal x,w,y,bottom,th,wth; SNES_FAS *curfas = fas; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); ierr = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr); bottom = y - th; while (curfas) { if (!curfas->smoothu) { ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); } else { w = 0.5*PetscMin(1.0-x,x); ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); } /* this is totally bogus but we have no way of knowing how low the previous one was draw to */ bottom -= 5*th; if (curfas->next) curfas = (SNES_FAS*)curfas->next->data; else curfas = NULL; } } } PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL snesfascyclegetsmootherdown_(SNES snes,SNES *smoothd, int *__ierr ){ *__ierr = SNESFASCycleGetSmootherDown( (SNES)PetscToPointer((snes) ),smoothd); }