/*@ SNESFASGetInterpolation - Gets the matrix used to calculate the interpolation from l-1 to the lth level Input Parameters: + snes - the multigrid context - level - the level (0 is coarsest) to supply [do not supply 0] Output Parameters: . mat - the interpolation operator Level: advanced .keywords: FAS, multigrid, get, interpolate, level .seealso: SNESFASSetInterpolation(), SNESFASGetInjection(), SNESFASGetRestriction(), SNESFASGetRScale() @*/ PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat) { SNES_FAS *fas; PetscErrorCode ierr; SNES levelsnes; PetscFunctionBegin; ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; *mat = fas->interpolate; PetscFunctionReturn(0); }
/*@ SNESFASSetInjection - Sets the function to be used to inject the solution from level l to l-1. Input Parameters: + snes - the multigrid context . mat - the restriction matrix - level - the level (0 is coarsest) to supply [Do not supply 0] Level: advanced Notes: If you do not set this, the restriction and rscale is used to project the solution instead. .keywords: FAS, MG, set, multigrid, restriction, level .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction() @*/ PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat) { SNES_FAS *fas; PetscErrorCode ierr; SNES levelsnes; PetscFunctionBegin; ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); fas->inject = mat; PetscFunctionReturn(0); }
/*@ SNESFASGetSmoother - Gets the default smoother on a level. Input Parameters: + snes - the multigrid context - level - the level (0 is coarsest) to supply Output Parameters: smooth - the smoother Level: advanced .keywords: FAS, MG, get, multigrid, smoother, level .seealso: SNESFASSetInjection(), SNESFASSetRestriction() @*/ PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth) { SNES_FAS *fas; PetscErrorCode ierr; SNES levelsnes; PetscFunctionBegin; ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; if (!fas->smoothd) { ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr); } *smooth = fas->smoothd; PetscFunctionReturn(0); }
/*@ SNESFASSetRScale - Sets the scaling factor of the restriction operator from level l to l-1. Input Parameters: + snes - the multigrid context . rscale - the restriction scaling - level - the level (0 is coarsest) to supply [Do not supply 0] Level: advanced Notes: This is only used in the case that the injection is not set. .keywords: FAS, MG, set, multigrid, restriction, level .seealso: SNESFASSetInjection(), SNESFASSetRestriction() @*/ PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale) { SNES_FAS *fas; PetscErrorCode ierr; SNES levelsnes; PetscFunctionBegin; ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr); ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); fas->rscale = rscale; PetscFunctionReturn(0); }
/*@ SNESFASGetCoarseSolve - Gets the coarsest solver. Input Parameters: + snes - the multigrid context Output Parameters: solve - the coarse-level solver Level: advanced .keywords: FAS, MG, get, multigrid, solver, coarse .seealso: SNESFASSetInjection(), SNESFASSetRestriction() @*/ PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *smooth) { SNES_FAS *fas; PetscErrorCode ierr; SNES levelsnes; PetscFunctionBegin; ierr = SNESFASGetCycleSNES(snes, 0, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; /* if the user chooses to differentiate smoothers, create them both at this point */ if (!fas->smoothd) { ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr); } *smooth = fas->smoothd; PetscFunctionReturn(0); }
/*@ SNESFASSetLog - Sets or unsets time logging for various FAS stages on all levels Logically Collective on SNES Input Parameters: + snes - the FAS context - flg - monitor or not Level: advanced .keywords: FAS, logging .seealso: SNESFASSetMonitor() @*/ PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg) { SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr; PetscBool isFine; PetscInt i, levels = fas->levels; SNES levelsnes; char eventname[128]; PetscFunctionBegin; ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); if (isFine) { for (i = 0; i < levels; i++) { ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); fas = (SNES_FAS*)levelsnes->data; if (flg) { sprintf(eventname,"FASSetup %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsetup);CHKERRQ(ierr); sprintf(eventname,"FASSmooth %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsolve);CHKERRQ(ierr); sprintf(eventname,"FASResid %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventresidual);CHKERRQ(ierr); if (i) { sprintf(eventname,"FASInterp %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventinterprestrict);CHKERRQ(ierr); } } else { fas->eventsmoothsetup = 0; fas->eventsmoothsolve = 0; fas->eventresidual = 0; fas->eventinterprestrict = 0; } } } 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 snesfasgetcyclesnes_(SNES snes,PetscInt *level,SNES *lsnes, int *__ierr ){ *__ierr = SNESFASGetCycleSNES( (SNES)PetscToPointer((snes) ),*level,lsnes); }