137eeb815SJakub Kruzik 237eeb815SJakub Kruzik /* -------------------------------------------------------------------- 337eeb815SJakub Kruzik 437eeb815SJakub Kruzik This file implements a Deflation preconditioner in PETSc as part of PC. 537eeb815SJakub Kruzik You can use this as a starting point for implementing your own 637eeb815SJakub Kruzik preconditioner that is not provided with PETSc. (You might also consider 737eeb815SJakub Kruzik just using PCSHELL) 837eeb815SJakub Kruzik 937eeb815SJakub Kruzik The following basic routines are required for each preconditioner. 1037eeb815SJakub Kruzik PCCreate_XXX() - Creates a preconditioner context 1137eeb815SJakub Kruzik PCSetFromOptions_XXX() - Sets runtime options 1237eeb815SJakub Kruzik PCApply_XXX() - Applies the preconditioner 1337eeb815SJakub Kruzik PCDestroy_XXX() - Destroys the preconditioner context 1437eeb815SJakub Kruzik where the suffix "_XXX" denotes a particular implementation, in 1537eeb815SJakub Kruzik this case we use _Deflation (e.g., PCCreate_Deflation, PCApply_Deflation). 1637eeb815SJakub Kruzik These routines are actually called via the common user interface 1737eeb815SJakub Kruzik routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(), 1837eeb815SJakub Kruzik so the application code interface remains identical for all 1937eeb815SJakub Kruzik preconditioners. 2037eeb815SJakub Kruzik 2137eeb815SJakub Kruzik Another key routine is: 2237eeb815SJakub Kruzik PCSetUp_XXX() - Prepares for the use of a preconditioner 2337eeb815SJakub Kruzik by setting data structures and options. The interface routine PCSetUp() 2437eeb815SJakub Kruzik is not usually called directly by the user, but instead is called by 2537eeb815SJakub Kruzik PCApply() if necessary. 2637eeb815SJakub Kruzik 2737eeb815SJakub Kruzik Additional basic routines are: 2837eeb815SJakub Kruzik PCView_XXX() - Prints details of runtime options that 2937eeb815SJakub Kruzik have actually been used. 3037eeb815SJakub Kruzik These are called by application codes via the interface routines 3137eeb815SJakub Kruzik PCView(). 3237eeb815SJakub Kruzik 3337eeb815SJakub Kruzik The various types of solvers (preconditioners, Krylov subspace methods, 3437eeb815SJakub Kruzik nonlinear solvers, timesteppers) are all organized similarly, so the 3537eeb815SJakub Kruzik above description applies to these categories also. One exception is 3637eeb815SJakub Kruzik that the analogues of PCApply() for these components are KSPSolve(), 3737eeb815SJakub Kruzik SNESSolve(), and TSSolve(). 3837eeb815SJakub Kruzik 3937eeb815SJakub Kruzik Additional optional functionality unique to preconditioners is left and 4037eeb815SJakub Kruzik right symmetric preconditioner application via PCApplySymmetricLeft() 4137eeb815SJakub Kruzik and PCApplySymmetricRight(). The Deflation implementation is 4237eeb815SJakub Kruzik PCApplySymmetricLeftOrRight_Deflation(). 4337eeb815SJakub Kruzik 4437eeb815SJakub Kruzik -------------------------------------------------------------------- */ 4537eeb815SJakub Kruzik 4637eeb815SJakub Kruzik /* 4737eeb815SJakub Kruzik Include files needed for the Deflation preconditioner: 4837eeb815SJakub Kruzik pcimpl.h - private include file intended for use by all preconditioners 4937eeb815SJakub Kruzik */ 5037eeb815SJakub Kruzik 51292e2e67SJakub Kruzik #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 5237eeb815SJakub Kruzik 538513960bSJakub Kruzik const char *const PCDeflationSpaceTypes[] = { 548513960bSJakub Kruzik "haar", 558513960bSJakub Kruzik "jacket-haar", 568513960bSJakub Kruzik "db2", 578513960bSJakub Kruzik "db4", 588513960bSJakub Kruzik "db8", 598513960bSJakub Kruzik "db16", 608513960bSJakub Kruzik "biorth22", 618513960bSJakub Kruzik "meyer", 628513960bSJakub Kruzik "aggregation", 638513960bSJakub Kruzik "slepc", 648513960bSJakub Kruzik "slepc-cheap", 658513960bSJakub Kruzik "user", 668513960bSJakub Kruzik "DdefSpaceType", 678513960bSJakub Kruzik "Ddef_SPACE_", 688513960bSJakub Kruzik 0 698513960bSJakub Kruzik }; 708513960bSJakub Kruzik 7198d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max) 7298d6e3deSJakub Kruzik { 7398d6e3deSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 7498d6e3deSJakub Kruzik 7598d6e3deSJakub Kruzik PetscFunctionBegin; 7698d6e3deSJakub Kruzik if (current) def->nestedlvl = current; 7798d6e3deSJakub Kruzik def->maxnestedlvl = max; 7898d6e3deSJakub Kruzik PetscFunctionReturn(0); 7998d6e3deSJakub Kruzik } 8098d6e3deSJakub Kruzik 8198d6e3deSJakub Kruzik /*@ 8298d6e3deSJakub Kruzik PCDeflationSetMaxLvl - Set maximum level of deflation. 8398d6e3deSJakub Kruzik 8498d6e3deSJakub Kruzik Logically Collective on PC 8598d6e3deSJakub Kruzik 8698d6e3deSJakub Kruzik Input Parameters: 8798d6e3deSJakub Kruzik + pc - the preconditioner context 8898d6e3deSJakub Kruzik - max - maximum deflation level 8998d6e3deSJakub Kruzik 9098d6e3deSJakub Kruzik Level: intermediate 9198d6e3deSJakub Kruzik 9298d6e3deSJakub Kruzik .seealso: PCDEFLATION 9398d6e3deSJakub Kruzik @*/ 9498d6e3deSJakub Kruzik PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max) 9598d6e3deSJakub Kruzik { 9698d6e3deSJakub Kruzik PetscErrorCode ierr; 9798d6e3deSJakub Kruzik 9898d6e3deSJakub Kruzik PetscFunctionBegin; 9998d6e3deSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 10098d6e3deSJakub Kruzik PetscValidLogicalCollectiveInt(pc,max,2); 10198d6e3deSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr); 10298d6e3deSJakub Kruzik PetscFunctionReturn(0); 10398d6e3deSJakub Kruzik } 10498d6e3deSJakub Kruzik 105*859a873cSJakub Kruzik static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red) 106*859a873cSJakub Kruzik { 107*859a873cSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 108*859a873cSJakub Kruzik 109*859a873cSJakub Kruzik PetscFunctionBegin; 110*859a873cSJakub Kruzik def->reductionfact = red; 111*859a873cSJakub Kruzik PetscFunctionReturn(0); 112*859a873cSJakub Kruzik } 113*859a873cSJakub Kruzik 114*859a873cSJakub Kruzik /*@ 115*859a873cSJakub Kruzik PCDeflationSetReductionFactor - Set reduction factor for PCTELESCOPE coarse problem solver. 116*859a873cSJakub Kruzik 117*859a873cSJakub Kruzik Logically Collective on PC 118*859a873cSJakub Kruzik 119*859a873cSJakub Kruzik Input Parameters: 120*859a873cSJakub Kruzik + pc - the preconditioner context 121*859a873cSJakub Kruzik - red - reduction factor (or PETSC_DETERMINE) 122*859a873cSJakub Kruzik 123*859a873cSJakub Kruzik Level: intermediate 124*859a873cSJakub Kruzik 125*859a873cSJakub Kruzik .seealso: PCDEFLATION 126*859a873cSJakub Kruzik @*/ 127*859a873cSJakub Kruzik PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red) 128*859a873cSJakub Kruzik { 129*859a873cSJakub Kruzik PetscErrorCode ierr; 130*859a873cSJakub Kruzik 131*859a873cSJakub Kruzik PetscFunctionBegin; 132*859a873cSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 133*859a873cSJakub Kruzik PetscValidLogicalCollectiveInt(pc,red,2); 134*859a873cSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr); 135*859a873cSJakub Kruzik PetscFunctionReturn(0); 136*859a873cSJakub Kruzik } 137*859a873cSJakub Kruzik 13839417d7eSJakub Kruzik static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size) 13939417d7eSJakub Kruzik { 14039417d7eSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 14139417d7eSJakub Kruzik 14239417d7eSJakub Kruzik PetscFunctionBegin; 14339417d7eSJakub Kruzik if (type) def->spacetype = type; 14439417d7eSJakub Kruzik if (size > 0) def->spacesize = size; 14539417d7eSJakub Kruzik PetscFunctionReturn(0); 14639417d7eSJakub Kruzik } 14739417d7eSJakub Kruzik 14839417d7eSJakub Kruzik /*@ 14939417d7eSJakub Kruzik PCDeflationSetSpaceToCompute - Set deflation space type and size to compute. 15039417d7eSJakub Kruzik 15139417d7eSJakub Kruzik Logically Collective on PC 15239417d7eSJakub Kruzik 15339417d7eSJakub Kruzik Input Parameters: 15439417d7eSJakub Kruzik + pc - the preconditioner context 15539417d7eSJakub Kruzik . type - deflation space type to compute (or PETSC_IGNORE) 15639417d7eSJakub Kruzik - size - size of the space to compute (or PETSC_DEFAULT) 15739417d7eSJakub Kruzik 15839417d7eSJakub Kruzik Notes: 15939417d7eSJakub Kruzik For wavelet-based deflation, size represents number of levels. 16039417d7eSJakub Kruzik The deflation space is computed in PCSetUP(). 16139417d7eSJakub Kruzik 16239417d7eSJakub Kruzik Level: intermediate 16339417d7eSJakub Kruzik 16439417d7eSJakub Kruzik .seealso: PCDEFLATION 16539417d7eSJakub Kruzik @*/ 16639417d7eSJakub Kruzik PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size) 16739417d7eSJakub Kruzik { 16839417d7eSJakub Kruzik PetscErrorCode ierr; 16939417d7eSJakub Kruzik 17039417d7eSJakub Kruzik PetscFunctionBegin; 17139417d7eSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 17239417d7eSJakub Kruzik if (type) PetscValidLogicalCollectiveEnum(pc,type,2); 17339417d7eSJakub Kruzik if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3); 17439417d7eSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr); 17539417d7eSJakub Kruzik PetscFunctionReturn(0); 17639417d7eSJakub Kruzik } 1778513960bSJakub Kruzik 178e662bc50SJakub Kruzik static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose) 179e662bc50SJakub Kruzik { 180e662bc50SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 181e662bc50SJakub Kruzik PetscErrorCode ierr; 182e662bc50SJakub Kruzik 183e662bc50SJakub Kruzik PetscFunctionBegin; 184e662bc50SJakub Kruzik if (transpose) { 185e662bc50SJakub Kruzik def->Wt = W; 186e662bc50SJakub Kruzik def->W = NULL; 187e662bc50SJakub Kruzik } else { 188e662bc50SJakub Kruzik def->W = W; 189e662bc50SJakub Kruzik } 190e662bc50SJakub Kruzik ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr); 191e662bc50SJakub Kruzik PetscFunctionReturn(0); 192e662bc50SJakub Kruzik } 193e662bc50SJakub Kruzik 194e662bc50SJakub Kruzik /* TODO create PCDeflationSetSpaceTranspose? */ 195e662bc50SJakub Kruzik /*@ 196e662bc50SJakub Kruzik PCDeflationSetSpace - Set deflation space matrix (or its transpose). 197e662bc50SJakub Kruzik 198e662bc50SJakub Kruzik Logically Collective on PC 199e662bc50SJakub Kruzik 200e662bc50SJakub Kruzik Input Parameters: 201e662bc50SJakub Kruzik + pc - the preconditioner context 202e662bc50SJakub Kruzik . W - deflation matrix 203e662bc50SJakub Kruzik - tranpose - indicates that W is an explicit transpose of the deflation matrix 204e662bc50SJakub Kruzik 205e662bc50SJakub Kruzik Level: intermediate 206e662bc50SJakub Kruzik 207e662bc50SJakub Kruzik .seealso: PCDEFLATION 208e662bc50SJakub Kruzik @*/ 209e662bc50SJakub Kruzik PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose) 210e662bc50SJakub Kruzik { 211e662bc50SJakub Kruzik PetscErrorCode ierr; 212e662bc50SJakub Kruzik 213e662bc50SJakub Kruzik PetscFunctionBegin; 214e662bc50SJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 215e662bc50SJakub Kruzik PetscValidHeaderSpecific(W,MAT_CLASSID,2); 216e662bc50SJakub Kruzik PetscValidLogicalCollectiveBool(pc,transpose,3); 217e662bc50SJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr); 218e662bc50SJakub Kruzik PetscFunctionReturn(0); 219e662bc50SJakub Kruzik } 220e662bc50SJakub Kruzik 2213cf3a049SJakub Kruzik static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat) 2223cf3a049SJakub Kruzik { 2233cf3a049SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 2243cf3a049SJakub Kruzik PetscErrorCode ierr; 2253cf3a049SJakub Kruzik 2263cf3a049SJakub Kruzik PetscFunctionBegin; 2273cf3a049SJakub Kruzik ierr = MatDestroy(&def->WtA);CHKERRQ(ierr); 2283cf3a049SJakub Kruzik def->WtA = mat; 2293cf3a049SJakub Kruzik ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 2303cf3a049SJakub Kruzik ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr); 2313cf3a049SJakub Kruzik PetscFunctionReturn(0); 2323cf3a049SJakub Kruzik } 2333cf3a049SJakub Kruzik 2343cf3a049SJakub Kruzik /*@ 2353cf3a049SJakub Kruzik PCDeflationSetProjectionNullSpaceMat - Set projection null space matrix (W'*A). 2363cf3a049SJakub Kruzik 2373cf3a049SJakub Kruzik Not Collective 2383cf3a049SJakub Kruzik 2393cf3a049SJakub Kruzik Input Parameters: 2403cf3a049SJakub Kruzik + pc - preconditioner context 2413cf3a049SJakub Kruzik - mat - projection null space matrix 2423cf3a049SJakub Kruzik 2433cf3a049SJakub Kruzik Level: developer 2443cf3a049SJakub Kruzik 2453cf3a049SJakub Kruzik .seealso: PCDEFLATION 2463cf3a049SJakub Kruzik @*/ 2473cf3a049SJakub Kruzik PetscErrorCode PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat) 2483cf3a049SJakub Kruzik { 2493cf3a049SJakub Kruzik PetscErrorCode ierr; 2503cf3a049SJakub Kruzik 2513cf3a049SJakub Kruzik PetscFunctionBegin; 2523cf3a049SJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 2533cf3a049SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 2543cf3a049SJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr); 2553cf3a049SJakub Kruzik PetscFunctionReturn(0); 2563cf3a049SJakub Kruzik } 2573cf3a049SJakub Kruzik 258e924b002SJakub Kruzik static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat) 259e924b002SJakub Kruzik { 260e924b002SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 261e924b002SJakub Kruzik PetscErrorCode ierr; 262e924b002SJakub Kruzik 263e924b002SJakub Kruzik PetscFunctionBegin; 264e924b002SJakub Kruzik ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr); 265e924b002SJakub Kruzik def->WtAW = mat; 266e924b002SJakub Kruzik ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 267e924b002SJakub Kruzik ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr); 268e924b002SJakub Kruzik PetscFunctionReturn(0); 269e924b002SJakub Kruzik } 270e924b002SJakub Kruzik 271e924b002SJakub Kruzik /*@ 272e924b002SJakub Kruzik PCDeflationSetCoarseMat - Set coarse problem Mat. 273e924b002SJakub Kruzik 274e924b002SJakub Kruzik Not Collective 275e924b002SJakub Kruzik 276e924b002SJakub Kruzik Input Parameters: 277e924b002SJakub Kruzik + pc - preconditioner context 278e924b002SJakub Kruzik - mat - coarse problem mat 279e924b002SJakub Kruzik 280e924b002SJakub Kruzik Level: developer 281e924b002SJakub Kruzik 282e924b002SJakub Kruzik .seealso: PCDEFLATION 283e924b002SJakub Kruzik @*/ 284e924b002SJakub Kruzik PetscErrorCode PCDeflationSetCoarseMat(PC pc,Mat mat) 285e924b002SJakub Kruzik { 286e924b002SJakub Kruzik PetscErrorCode ierr; 287e924b002SJakub Kruzik 288e924b002SJakub Kruzik PetscFunctionBegin; 289e924b002SJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 290e924b002SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 291e924b002SJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr); 292e924b002SJakub Kruzik PetscFunctionReturn(0); 293e924b002SJakub Kruzik } 294e924b002SJakub Kruzik 29598d6e3deSJakub Kruzik static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp) 2965c0c31c5SJakub Kruzik { 2975c0c31c5SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 2985c0c31c5SJakub Kruzik 2995c0c31c5SJakub Kruzik PetscFunctionBegin; 30098d6e3deSJakub Kruzik *ksp = def->WtAWinv; 3015c0c31c5SJakub Kruzik PetscFunctionReturn(0); 3025c0c31c5SJakub Kruzik } 3035c0c31c5SJakub Kruzik 3045c0c31c5SJakub Kruzik /*@ 30598d6e3deSJakub Kruzik PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP. 3065c0c31c5SJakub Kruzik 30798d6e3deSJakub Kruzik Not Collective 3085c0c31c5SJakub Kruzik 3095c0c31c5SJakub Kruzik Input Parameters: 31098d6e3deSJakub Kruzik . pc - preconditioner context 3115c0c31c5SJakub Kruzik 31298d6e3deSJakub Kruzik Output Parameter: 31398d6e3deSJakub Kruzik . ksp - coarse problem KSP context 3145c0c31c5SJakub Kruzik 31598d6e3deSJakub Kruzik Level: developer 31698d6e3deSJakub Kruzik 31798d6e3deSJakub Kruzik .seealso: PCDeflationSetCoarseKSP(), PCDEFLATION 3185c0c31c5SJakub Kruzik @*/ 31998d6e3deSJakub Kruzik PetscErrorCode PCDeflationGetCoarseKSP(PC pc,KSP *ksp) 3205c0c31c5SJakub Kruzik { 3215c0c31c5SJakub Kruzik PetscErrorCode ierr; 3225c0c31c5SJakub Kruzik 3235c0c31c5SJakub Kruzik PetscFunctionBegin; 32422b0793eSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 32598d6e3deSJakub Kruzik PetscValidPointer(ksp,2); 32698d6e3deSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr); 32798d6e3deSJakub Kruzik PetscFunctionReturn(0); 32898d6e3deSJakub Kruzik } 32998d6e3deSJakub Kruzik 33098d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetCoarseKSP_Deflation(PC pc,KSP ksp) 33198d6e3deSJakub Kruzik { 33298d6e3deSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 33398d6e3deSJakub Kruzik PetscErrorCode ierr; 33498d6e3deSJakub Kruzik 33598d6e3deSJakub Kruzik PetscFunctionBegin; 33698d6e3deSJakub Kruzik ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr); 33798d6e3deSJakub Kruzik def->WtAWinv = ksp; 33898d6e3deSJakub Kruzik ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr); 33998d6e3deSJakub Kruzik ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAWinv);CHKERRQ(ierr); 34098d6e3deSJakub Kruzik PetscFunctionReturn(0); 34198d6e3deSJakub Kruzik } 34298d6e3deSJakub Kruzik 34398d6e3deSJakub Kruzik /*@ 34498d6e3deSJakub Kruzik PCDeflationSetCoarseKSP - Set coarse problem KSP. 34598d6e3deSJakub Kruzik 34698d6e3deSJakub Kruzik Collective on PC 34798d6e3deSJakub Kruzik 34898d6e3deSJakub Kruzik Input Parameters: 34998d6e3deSJakub Kruzik + pc - preconditioner context 35098d6e3deSJakub Kruzik - ksp - coarse problem KSP context 35198d6e3deSJakub Kruzik 35298d6e3deSJakub Kruzik Level: developer 35398d6e3deSJakub Kruzik 35498d6e3deSJakub Kruzik .seealso: PCDeflationGetCoarseKSP(), PCDEFLATION 35598d6e3deSJakub Kruzik @*/ 35698d6e3deSJakub Kruzik PetscErrorCode PCDeflationSetCoarseKSP(PC pc,KSP ksp) 35798d6e3deSJakub Kruzik { 35898d6e3deSJakub Kruzik PetscErrorCode ierr; 35998d6e3deSJakub Kruzik 36098d6e3deSJakub Kruzik PetscFunctionBegin; 36198d6e3deSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 36298d6e3deSJakub Kruzik PetscValidHeaderSpecific(ksp,KSP_CLASSID,2); 36398d6e3deSJakub Kruzik PetscCheckSameComm(pc,1,ksp,2); 36498d6e3deSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetCoarseKSP_C",(PC,KSP),(pc,ksp));CHKERRQ(ierr); 3655c0c31c5SJakub Kruzik PetscFunctionReturn(0); 3665c0c31c5SJakub Kruzik } 367e662bc50SJakub Kruzik 368268c6673SJakub Kruzik static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc) 369268c6673SJakub Kruzik { 370268c6673SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 371268c6673SJakub Kruzik 372268c6673SJakub Kruzik PetscFunctionBegin; 373268c6673SJakub Kruzik *apc = def->pc; 374268c6673SJakub Kruzik PetscFunctionReturn(0); 375268c6673SJakub Kruzik } 376268c6673SJakub Kruzik 377268c6673SJakub Kruzik /*@ 378268c6673SJakub Kruzik PCDeflationGetPC - Returns a pointer to additional preconditioner. 379268c6673SJakub Kruzik 380268c6673SJakub Kruzik Not Collective 381268c6673SJakub Kruzik 382268c6673SJakub Kruzik Input Parameters: 383268c6673SJakub Kruzik . pc - the preconditioner context 384268c6673SJakub Kruzik 385268c6673SJakub Kruzik Output Parameter: 386268c6673SJakub Kruzik . apc - additional preconditioner 387268c6673SJakub Kruzik 388268c6673SJakub Kruzik Level: advanced 389268c6673SJakub Kruzik 390268c6673SJakub Kruzik .seealso: PCDeflationSetPC(), PCDEFLATION 391268c6673SJakub Kruzik @*/ 392268c6673SJakub Kruzik PetscErrorCode PCDeflationGetPC(PC pc,PC *apc) 393268c6673SJakub Kruzik { 394268c6673SJakub Kruzik PetscErrorCode ierr; 395268c6673SJakub Kruzik 396268c6673SJakub Kruzik PetscFunctionBegin; 397268c6673SJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 398268c6673SJakub Kruzik PetscValidPointer(pc,2); 399268c6673SJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr); 400268c6673SJakub Kruzik PetscFunctionReturn(0); 401268c6673SJakub Kruzik } 402268c6673SJakub Kruzik 40322b0793eSJakub Kruzik static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc) 40422b0793eSJakub Kruzik { 40522b0793eSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 40622b0793eSJakub Kruzik PetscErrorCode ierr; 40722b0793eSJakub Kruzik 40822b0793eSJakub Kruzik PetscFunctionBegin; 40922b0793eSJakub Kruzik ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 41022b0793eSJakub Kruzik def->pc = apc; 41122b0793eSJakub Kruzik ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr); 41222b0793eSJakub Kruzik ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr); 41322b0793eSJakub Kruzik PetscFunctionReturn(0); 41422b0793eSJakub Kruzik } 41522b0793eSJakub Kruzik 41622b0793eSJakub Kruzik /*@ 41722b0793eSJakub Kruzik PCDeflationSetPC - Set additional preconditioner. 41822b0793eSJakub Kruzik 419268c6673SJakub Kruzik Collective on PC 42022b0793eSJakub Kruzik 42122b0793eSJakub Kruzik Input Parameters: 42222b0793eSJakub Kruzik + pc - the preconditioner context 42322b0793eSJakub Kruzik - apc - additional preconditioner 42422b0793eSJakub Kruzik 425268c6673SJakub Kruzik Level: developer 42622b0793eSJakub Kruzik 427268c6673SJakub Kruzik .seealso: PCDeflationGetPC(), PCDEFLATION 42822b0793eSJakub Kruzik @*/ 42922b0793eSJakub Kruzik PetscErrorCode PCDeflationSetPC(PC pc,PC apc) 43022b0793eSJakub Kruzik { 43122b0793eSJakub Kruzik PetscErrorCode ierr; 43222b0793eSJakub Kruzik 43322b0793eSJakub Kruzik PetscFunctionBegin; 43422b0793eSJakub Kruzik PetscValidHeaderSpecific(pc,PC_CLASSID,1); 43522b0793eSJakub Kruzik PetscValidHeaderSpecific(apc,PC_CLASSID,2); 43622b0793eSJakub Kruzik PetscCheckSameComm(pc,1,apc,2); 43722b0793eSJakub Kruzik ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr); 43822b0793eSJakub Kruzik PetscFunctionReturn(0); 43922b0793eSJakub Kruzik } 44022b0793eSJakub Kruzik 44137eeb815SJakub Kruzik /* 442b27c8092SJakub Kruzik x <- x + W*(W'*A*W)^{-1}*W'*r = x + Q*r 443b27c8092SJakub Kruzik */ 444b27c8092SJakub Kruzik static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x) 445b27c8092SJakub Kruzik { 446b27c8092SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 447b27c8092SJakub Kruzik Mat A; 448b27c8092SJakub Kruzik Vec r,w1,w2; 449b27c8092SJakub Kruzik PetscBool nonzero; 450b27c8092SJakub Kruzik PetscErrorCode ierr; 45137eeb815SJakub Kruzik 452b27c8092SJakub Kruzik PetscFunctionBegin; 453b27c8092SJakub Kruzik w1 = def->workcoarse[0]; 454b27c8092SJakub Kruzik w2 = def->workcoarse[1]; 455b27c8092SJakub Kruzik r = def->work; 456b27c8092SJakub Kruzik ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 45737eeb815SJakub Kruzik 458b27c8092SJakub Kruzik ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr); 459b27c8092SJakub Kruzik ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 460b27c8092SJakub Kruzik if (nonzero) { 461b27c8092SJakub Kruzik ierr = MatMult(A,x,r);CHKERRQ(ierr); /* r <- b - Ax */ 462b27c8092SJakub Kruzik ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); 463b27c8092SJakub Kruzik } else { 464b27c8092SJakub Kruzik ierr = VecCopy(b,r);CHKERRQ(ierr); /* r <- b (x is 0) */ 465b27c8092SJakub Kruzik } 466b27c8092SJakub Kruzik 467a3177931SJakub Kruzik if (def->Wt) { 468a3177931SJakub Kruzik ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr); /* w1 <- W'*r */ 469a3177931SJakub Kruzik } else { 470a3177931SJakub Kruzik ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr); /* w1 <- W'*r */ 471a3177931SJakub Kruzik } 472b27c8092SJakub Kruzik ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 473b27c8092SJakub Kruzik ierr = MatMult(def->W,w2,r);CHKERRQ(ierr); /* r <- W*w2 */ 474b27c8092SJakub Kruzik ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr); 475b27c8092SJakub Kruzik PetscFunctionReturn(0); 476b27c8092SJakub Kruzik } 47737eeb815SJakub Kruzik 478f8bf229cSJakub Kruzik /* 479f8bf229cSJakub Kruzik if (def->correct) { 480ae029463SJakub Kruzik z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r 481f8bf229cSJakub Kruzik } else { 482ae029463SJakub Kruzik z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r 483f8bf229cSJakub Kruzik } 48437eeb815SJakub Kruzik */ 485f8bf229cSJakub Kruzik static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z) 486f8bf229cSJakub Kruzik { 487f8bf229cSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 488f8bf229cSJakub Kruzik Mat A; 489f8bf229cSJakub Kruzik Vec u,w1,w2; 490f8bf229cSJakub Kruzik PetscErrorCode ierr; 491f8bf229cSJakub Kruzik 492f8bf229cSJakub Kruzik PetscFunctionBegin; 493f8bf229cSJakub Kruzik w1 = def->workcoarse[0]; 494f8bf229cSJakub Kruzik w2 = def->workcoarse[1]; 495f8bf229cSJakub Kruzik u = def->work; 496f8bf229cSJakub Kruzik ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 497f8bf229cSJakub Kruzik 498ae029463SJakub Kruzik ierr = PCApply(def->pc,r,z);CHKERRQ(ierr); /* z <- M^{-1}*r */ 49922b0793eSJakub Kruzik if (!def->init) { 500ae029463SJakub Kruzik ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr); /* w1 <- W'*A*z */ 501f8bf229cSJakub Kruzik if (def->correct) { 502ae029463SJakub Kruzik if (def->Wt) { 503ae029463SJakub Kruzik ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr); /* w2 <- W'*r */ 504ae029463SJakub Kruzik } else { 505a3177931SJakub Kruzik ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr); /* w2 <- W'*r */ 506f8bf229cSJakub Kruzik } 507ae029463SJakub Kruzik ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr); /* w1 <- w1 - l*w2 */ 508f8bf229cSJakub Kruzik } 509f8bf229cSJakub Kruzik ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 510f8bf229cSJakub Kruzik ierr = MatMult(def->W,w2,u);CHKERRQ(ierr); /* u <- W*w2 */ 51122b0793eSJakub Kruzik ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr); /* z <- z - u */ 51222b0793eSJakub Kruzik } 513f8bf229cSJakub Kruzik PetscFunctionReturn(0); 514f8bf229cSJakub Kruzik } 515f8bf229cSJakub Kruzik 51637eeb815SJakub Kruzik static PetscErrorCode PCSetUp_Deflation(PC pc) 51737eeb815SJakub Kruzik { 518409a357bSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 519409a357bSJakub Kruzik KSP innerksp; 520409a357bSJakub Kruzik PC pcinner; 521409a357bSJakub Kruzik Mat Amat,nextDef=NULL,*mats; 522409a357bSJakub Kruzik PetscInt i,m,red,size,commsize; 523409a357bSJakub Kruzik PetscBool match,flgspd,transp=PETSC_FALSE; 524409a357bSJakub Kruzik MatCompositeType ctype; 525409a357bSJakub Kruzik MPI_Comm comm; 526409a357bSJakub Kruzik const char *prefix; 52737eeb815SJakub Kruzik PetscErrorCode ierr; 52837eeb815SJakub Kruzik 52937eeb815SJakub Kruzik PetscFunctionBegin; 530409a357bSJakub Kruzik if (pc->setupcalled) PetscFunctionReturn(0); 531409a357bSJakub Kruzik ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 532f8bf229cSJakub Kruzik ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr); 533f8bf229cSJakub Kruzik 534f8bf229cSJakub Kruzik /* compute a deflation space */ 535409a357bSJakub Kruzik if (def->W || def->Wt) { 536409a357bSJakub Kruzik def->spacetype = PC_DEFLATION_SPACE_USER; 537409a357bSJakub Kruzik } else { 538e53e0a0dSJakub Kruzik ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr); 53937eeb815SJakub Kruzik } 54037eeb815SJakub Kruzik 541409a357bSJakub Kruzik /* nested deflation */ 542409a357bSJakub Kruzik if (def->W) { 543409a357bSJakub Kruzik ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr); 544409a357bSJakub Kruzik if (match) { 545409a357bSJakub Kruzik ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr); 546409a357bSJakub Kruzik ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr); 54737eeb815SJakub Kruzik } 548409a357bSJakub Kruzik } else { 549a3177931SJakub Kruzik ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr); 550409a357bSJakub Kruzik ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr); 551409a357bSJakub Kruzik if (match) { 552409a357bSJakub Kruzik ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr); 553409a357bSJakub Kruzik ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr); 554409a357bSJakub Kruzik } 555409a357bSJakub Kruzik transp = PETSC_TRUE; 556409a357bSJakub Kruzik } 557409a357bSJakub Kruzik if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) { 558409a357bSJakub Kruzik if (!transp) { 55928da0170SJakub Kruzik if (def->nestedlvl < def->maxnestedlvl) { 56028da0170SJakub Kruzik ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 561409a357bSJakub Kruzik for (i=0; i<size; i++) { 562409a357bSJakub Kruzik ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr); 563409a357bSJakub Kruzik } 564409a357bSJakub Kruzik size -= 1; 565409a357bSJakub Kruzik ierr = MatDestroy(&def->W);CHKERRQ(ierr); 566409a357bSJakub Kruzik def->W = mats[size]; 567409a357bSJakub Kruzik ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr); 568409a357bSJakub Kruzik if (size > 1) { 569409a357bSJakub Kruzik ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr); 570409a357bSJakub Kruzik ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 571409a357bSJakub Kruzik } else { 572409a357bSJakub Kruzik nextDef = mats[0]; 573409a357bSJakub Kruzik ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 574409a357bSJakub Kruzik } 57528da0170SJakub Kruzik ierr = PetscFree(mats);CHKERRQ(ierr); 576409a357bSJakub Kruzik } else { 577409a357bSJakub Kruzik /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 578409a357bSJakub Kruzik ierr = MatCompositeMerge(def->W);CHKERRQ(ierr); 579409a357bSJakub Kruzik } 58028da0170SJakub Kruzik } else { 58128da0170SJakub Kruzik if (def->nestedlvl < def->maxnestedlvl) { 58228da0170SJakub Kruzik ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 58328da0170SJakub Kruzik for (i=0; i<size; i++) { 58428da0170SJakub Kruzik ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr); 58528da0170SJakub Kruzik } 58628da0170SJakub Kruzik size -= 1; 58728da0170SJakub Kruzik ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 58828da0170SJakub Kruzik def->Wt = mats[0]; 58928da0170SJakub Kruzik ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 59028da0170SJakub Kruzik if (size > 1) { 59128da0170SJakub Kruzik ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr); 59228da0170SJakub Kruzik ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 59328da0170SJakub Kruzik } else { 59428da0170SJakub Kruzik nextDef = mats[1]; 59528da0170SJakub Kruzik ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr); 596409a357bSJakub Kruzik } 597409a357bSJakub Kruzik ierr = PetscFree(mats);CHKERRQ(ierr); 59828da0170SJakub Kruzik } else { 59928da0170SJakub Kruzik /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 60028da0170SJakub Kruzik ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr); 60128da0170SJakub Kruzik } 60228da0170SJakub Kruzik } 60328da0170SJakub Kruzik } 60428da0170SJakub Kruzik 60528da0170SJakub Kruzik if (transp) { 60628da0170SJakub Kruzik ierr = MatDestroy(&def->W);CHKERRQ(ierr); 607a3177931SJakub Kruzik ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr); 608409a357bSJakub Kruzik } 609409a357bSJakub Kruzik 61022b0793eSJakub Kruzik 61122b0793eSJakub Kruzik ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 61222b0793eSJakub Kruzik 613ae029463SJakub Kruzik /* assemble WtA */ 614ae029463SJakub Kruzik if (!def->WtA) { 615ae029463SJakub Kruzik if (def->Wt) { 616ae029463SJakub Kruzik ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 617ae029463SJakub Kruzik } else { 618a3177931SJakub Kruzik #if defined(PETSC_USE_COMPLEX) 619a3177931SJakub Kruzik ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr); 620a3177931SJakub Kruzik ierr = MatMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 621a3177931SJakub Kruzik #else 622ae029463SJakub Kruzik ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 623a3177931SJakub Kruzik #endif 624ae029463SJakub Kruzik } 625ae029463SJakub Kruzik } 626409a357bSJakub Kruzik /* setup coarse problem */ 627409a357bSJakub Kruzik if (!def->WtAWinv) { 62828da0170SJakub Kruzik ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr); 629409a357bSJakub Kruzik if (!def->WtAW) { 630ae029463SJakub Kruzik ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr); 631409a357bSJakub Kruzik /* TODO create MatInheritOption(Mat,MatOption) */ 632409a357bSJakub Kruzik ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr); 633409a357bSJakub Kruzik ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr); 634409a357bSJakub Kruzik #if defined(PETSC_USE_DEBUG) 635ae029463SJakub Kruzik /* Check columns of W are not in kernel of A */ 636409a357bSJakub Kruzik PetscReal *norms; 637409a357bSJakub Kruzik ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr); 638409a357bSJakub Kruzik ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr); 639409a357bSJakub Kruzik for (i=0; i<m; i++) { 640409a357bSJakub Kruzik if (norms[i] < 100*PETSC_MACHINE_EPSILON) { 641409a357bSJakub Kruzik SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i); 642409a357bSJakub Kruzik } 643409a357bSJakub Kruzik } 644409a357bSJakub Kruzik ierr = PetscFree(norms);CHKERRQ(ierr); 645409a357bSJakub Kruzik #endif 646409a357bSJakub Kruzik } else { 647409a357bSJakub Kruzik ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr); 648409a357bSJakub Kruzik } 649409a357bSJakub Kruzik /* TODO use MATINV */ 650409a357bSJakub Kruzik ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr); 651409a357bSJakub Kruzik ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr); 652409a357bSJakub Kruzik ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr); 653557a2f7dSJakub Kruzik /* Setup KSP and PC */ 654557a2f7dSJakub Kruzik if (nextDef) { /* next level for multilevel deflation */ 655557a2f7dSJakub Kruzik innerksp = def->WtAWinv; 656557a2f7dSJakub Kruzik /* set default KSPtype */ 657557a2f7dSJakub Kruzik if (!def->ksptype) { 658557a2f7dSJakub Kruzik def->ksptype = KSPFGMRES; 659557a2f7dSJakub Kruzik if (flgspd) { /* SPD system */ 660557a2f7dSJakub Kruzik def->ksptype = KSPFCG; 661557a2f7dSJakub Kruzik } 662557a2f7dSJakub Kruzik } 663ae029463SJakub Kruzik ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */ 664557a2f7dSJakub Kruzik ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */ 665557a2f7dSJakub Kruzik ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr); 666557a2f7dSJakub Kruzik ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr); 667ae029463SJakub Kruzik /* inherit options */ 668557a2f7dSJakub Kruzik ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype; 669557a2f7dSJakub Kruzik ((PC_Deflation*)(pcinner->data))->correct = def->correct; 670557a2f7dSJakub Kruzik ierr = MatDestroy(&nextDef);CHKERRQ(ierr); 671557a2f7dSJakub Kruzik } else { /* the last level */ 672557a2f7dSJakub Kruzik ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr); 673409a357bSJakub Kruzik ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr); 674ac66f006SJakub Kruzik /* ugly hack to not have overwritten PCTELESCOPE */ 675ac66f006SJakub Kruzik if (prefix) { 676ac66f006SJakub Kruzik ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr); 677ac66f006SJakub Kruzik } 67822b0793eSJakub Kruzik ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr); 679ac66f006SJakub Kruzik ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr); 680409a357bSJakub Kruzik /* Reduction factor choice */ 681409a357bSJakub Kruzik red = def->reductionfact; 682409a357bSJakub Kruzik if (red < 0) { 683409a357bSJakub Kruzik ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr); 684409a357bSJakub Kruzik red = ceil((float)commsize/ceil((float)m/commsize)); 685409a357bSJakub Kruzik ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr); 686409a357bSJakub Kruzik if (match) red = commsize; 687409a357bSJakub Kruzik ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */ 688409a357bSJakub Kruzik } 689409a357bSJakub Kruzik ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr); 690ac66f006SJakub Kruzik ierr = PCSetUp(pcinner);CHKERRQ(ierr); 691409a357bSJakub Kruzik ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr); 692ac66f006SJakub Kruzik if (innerksp) { 693409a357bSJakub Kruzik ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr); 694409a357bSJakub Kruzik /* TODO Cholesky if flgspd? */ 695ac66f006SJakub Kruzik ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr); 696409a357bSJakub Kruzik //TODO remove explicit matSolverPackage 697409a357bSJakub Kruzik if (commsize == red) { 698ac66f006SJakub Kruzik ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr); 699409a357bSJakub Kruzik } else { 700ac66f006SJakub Kruzik ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr); 701409a357bSJakub Kruzik } 702409a357bSJakub Kruzik } 703557a2f7dSJakub Kruzik } 704557a2f7dSJakub Kruzik 705557a2f7dSJakub Kruzik if (innerksp) { 706409a357bSJakub Kruzik /* TODO use def_[lvl]_ if lvl > 0? */ 707409a357bSJakub Kruzik if (prefix) { 708409a357bSJakub Kruzik ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr); 709409a357bSJakub Kruzik } 71022b0793eSJakub Kruzik ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr); 711557a2f7dSJakub Kruzik ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr); 712557a2f7dSJakub Kruzik ierr = KSPSetUp(innerksp);CHKERRQ(ierr); 713ac66f006SJakub Kruzik } 714409a357bSJakub Kruzik } 715557a2f7dSJakub Kruzik ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr); 716557a2f7dSJakub Kruzik ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr); 717409a357bSJakub Kruzik 71822b0793eSJakub Kruzik if (!def->pc) { 71922b0793eSJakub Kruzik ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr); 72022b0793eSJakub Kruzik ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr); 72122b0793eSJakub Kruzik ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr); 72222b0793eSJakub Kruzik if (prefix) { 72322b0793eSJakub Kruzik ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr); 72422b0793eSJakub Kruzik } 72522b0793eSJakub Kruzik ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr); 72622b0793eSJakub Kruzik ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr); 72722b0793eSJakub Kruzik ierr = PCSetUp(def->pc);CHKERRQ(ierr); 72822b0793eSJakub Kruzik } 72922b0793eSJakub Kruzik 730f8bf229cSJakub Kruzik /* create work vecs */ 731f8bf229cSJakub Kruzik ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr); 732f8bf229cSJakub Kruzik ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr); 73337eeb815SJakub Kruzik PetscFunctionReturn(0); 73437eeb815SJakub Kruzik } 735b30d4775SJakub Kruzik 73637eeb815SJakub Kruzik static PetscErrorCode PCReset_Deflation(PC pc) 73737eeb815SJakub Kruzik { 738b30d4775SJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 73937eeb815SJakub Kruzik PetscErrorCode ierr; 74037eeb815SJakub Kruzik 74137eeb815SJakub Kruzik PetscFunctionBegin; 742b30d4775SJakub Kruzik ierr = VecDestroy(&def->work);CHKERRQ(ierr); 743b30d4775SJakub Kruzik ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr); 744b30d4775SJakub Kruzik ierr = MatDestroy(&def->W);CHKERRQ(ierr); 745b30d4775SJakub Kruzik ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 746ae029463SJakub Kruzik ierr = MatDestroy(&def->WtA);CHKERRQ(ierr); 747b30d4775SJakub Kruzik ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr); 748b30d4775SJakub Kruzik ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr); 74922b0793eSJakub Kruzik ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 75037eeb815SJakub Kruzik PetscFunctionReturn(0); 75137eeb815SJakub Kruzik } 75237eeb815SJakub Kruzik 75337eeb815SJakub Kruzik /* 75437eeb815SJakub Kruzik PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner 75537eeb815SJakub Kruzik that was created with PCCreate_Deflation(). 75637eeb815SJakub Kruzik 75737eeb815SJakub Kruzik Input Parameter: 75837eeb815SJakub Kruzik . pc - the preconditioner context 75937eeb815SJakub Kruzik 76037eeb815SJakub Kruzik Application Interface Routine: PCDestroy() 76137eeb815SJakub Kruzik */ 76237eeb815SJakub Kruzik static PetscErrorCode PCDestroy_Deflation(PC pc) 76337eeb815SJakub Kruzik { 76437eeb815SJakub Kruzik PetscErrorCode ierr; 76537eeb815SJakub Kruzik 76637eeb815SJakub Kruzik PetscFunctionBegin; 76737eeb815SJakub Kruzik ierr = PCReset_Deflation(pc);CHKERRQ(ierr); 76837eeb815SJakub Kruzik ierr = PetscFree(pc->data);CHKERRQ(ierr); 76937eeb815SJakub Kruzik PetscFunctionReturn(0); 77037eeb815SJakub Kruzik } 77137eeb815SJakub Kruzik 7728513960bSJakub Kruzik static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer) 7738513960bSJakub Kruzik { 7748513960bSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 7758513960bSJakub Kruzik PetscBool iascii; 7768513960bSJakub Kruzik PetscErrorCode ierr; 7778513960bSJakub Kruzik 7788513960bSJakub Kruzik PetscFunctionBegin; 7798513960bSJakub Kruzik ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 7808513960bSJakub Kruzik if (iascii) { 7818513960bSJakub Kruzik //if (cg->adaptiveconv) { 7828513960bSJakub Kruzik // ierr = PetscViewerASCIIPrintf(viewer," DCG: using adaptive precision for inner solve with C=%.1e\n",cg->adaptiveconst);CHKERRQ(ierr); 7838513960bSJakub Kruzik //} 7848513960bSJakub Kruzik if (def->correct) { 7858513960bSJakub Kruzik ierr = PetscViewerASCIIPrintf(viewer," Using CP correction\n");CHKERRQ(ierr); 7868513960bSJakub Kruzik } 7878513960bSJakub Kruzik if (!def->nestedlvl) { 7888513960bSJakub Kruzik ierr = PetscViewerASCIIPrintf(viewer," Deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr); 7898513960bSJakub Kruzik ierr = PetscViewerASCIIPrintf(viewer," DCG %s\n",def->extendsp ? "extended" : "truncated");CHKERRQ(ierr); 7908513960bSJakub Kruzik } 7918513960bSJakub Kruzik 79222b0793eSJakub Kruzik ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC\n");CHKERRQ(ierr); 79322b0793eSJakub Kruzik ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 79422b0793eSJakub Kruzik ierr = PCView(def->pc,viewer);CHKERRQ(ierr); 79522b0793eSJakub Kruzik ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 79622b0793eSJakub Kruzik 7978513960bSJakub Kruzik ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse solver\n");CHKERRQ(ierr); 7988513960bSJakub Kruzik ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 7998513960bSJakub Kruzik ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr); 8008513960bSJakub Kruzik ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 8018513960bSJakub Kruzik } 8028513960bSJakub Kruzik PetscFunctionReturn(0); 8038513960bSJakub Kruzik } 8048513960bSJakub Kruzik 80537eeb815SJakub Kruzik static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc) 80637eeb815SJakub Kruzik { 807880d05ceSJakub Kruzik PC_Deflation *def = (PC_Deflation*)pc->data; 80837eeb815SJakub Kruzik PetscErrorCode ierr; 80937eeb815SJakub Kruzik 81037eeb815SJakub Kruzik PetscFunctionBegin; 81137eeb815SJakub Kruzik ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr); 812*859a873cSJakub Kruzik ierr = PetscOptionsInt("-pc_deflation_max_lvl","Maximum of deflation levels","PCDeflationSetMaxLvl",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr); 813*859a873cSJakub Kruzik ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr); 814880d05ceSJakub Kruzik ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr); 815880d05ceSJakub Kruzik ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr); 816880d05ceSJakub Kruzik ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr); 817880d05ceSJakub Kruzik //TODO add set function and fix manpages 818880d05ceSJakub Kruzik ierr = PetscOptionsBool("-pc_deflation_initdef","Use only initialization step - Initdef","PCDeflation",def->init,&def->init,NULL);CHKERRQ(ierr); 819fcb31d99SJakub Kruzik ierr = PetscOptionsBool("-pc_deflation_correct","Add coarse problem correction Q to P","PCDeflation",def->correct,&def->correct,NULL);CHKERRQ(ierr); 820fcb31d99SJakub Kruzik ierr = PetscOptionsReal("-pc_deflation_correct_val","Set multiple of Q to use as coarse problem correction","PCDeflation",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr); 82137eeb815SJakub Kruzik ierr = PetscOptionsTail();CHKERRQ(ierr); 82237eeb815SJakub Kruzik PetscFunctionReturn(0); 82337eeb815SJakub Kruzik } 82437eeb815SJakub Kruzik 82537eeb815SJakub Kruzik /*MC 826e361f8b5SJakub Kruzik PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates) 827e361f8b5SJakub Kruzik or to a predefined value 82837eeb815SJakub Kruzik 82937eeb815SJakub Kruzik Options Database Key: 830e361f8b5SJakub Kruzik + -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre) 83137eeb815SJakub Kruzik - -pc_jacobi_abs - use the absolute value of the diagonal entry 83237eeb815SJakub Kruzik 83337eeb815SJakub Kruzik Level: beginner 83437eeb815SJakub Kruzik 83537eeb815SJakub Kruzik Notes: 836e361f8b5SJakub Kruzik todo 83737eeb815SJakub Kruzik 83837eeb815SJakub Kruzik .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 839e662bc50SJakub Kruzik PCDeflationSetType(), PCDeflationSetSpace() 84037eeb815SJakub Kruzik M*/ 84137eeb815SJakub Kruzik 84237eeb815SJakub Kruzik PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc) 84337eeb815SJakub Kruzik { 84437eeb815SJakub Kruzik PC_Deflation *def; 84537eeb815SJakub Kruzik PetscErrorCode ierr; 84637eeb815SJakub Kruzik 84737eeb815SJakub Kruzik PetscFunctionBegin; 84837eeb815SJakub Kruzik ierr = PetscNewLog(pc,&def);CHKERRQ(ierr); 84937eeb815SJakub Kruzik pc->data = (void*)def; 85037eeb815SJakub Kruzik 851e662bc50SJakub Kruzik def->init = PETSC_FALSE; 852e662bc50SJakub Kruzik def->correct = PETSC_FALSE; 853fcb31d99SJakub Kruzik def->correctfact = 1.0; 854e662bc50SJakub Kruzik def->reductionfact = -1; 855e662bc50SJakub Kruzik def->spacetype = PC_DEFLATION_SPACE_HAAR; 856e662bc50SJakub Kruzik def->spacesize = 1; 857e662bc50SJakub Kruzik def->extendsp = PETSC_FALSE; 858e662bc50SJakub Kruzik def->nestedlvl = 0; 859e662bc50SJakub Kruzik def->maxnestedlvl = 0; 86037eeb815SJakub Kruzik 86137eeb815SJakub Kruzik /* 86237eeb815SJakub Kruzik Set the pointers for the functions that are provided above. 86337eeb815SJakub Kruzik Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 86437eeb815SJakub Kruzik are called, they will automatically call these functions. Note we 86537eeb815SJakub Kruzik choose not to provide a couple of these functions since they are 86637eeb815SJakub Kruzik not needed. 86737eeb815SJakub Kruzik */ 86837eeb815SJakub Kruzik pc->ops->apply = PCApply_Deflation; 86937eeb815SJakub Kruzik pc->ops->applytranspose = PCApply_Deflation; 870b27c8092SJakub Kruzik pc->ops->presolve = PCPreSolve_Deflation; 871b27c8092SJakub Kruzik pc->ops->postsolve = 0; 87237eeb815SJakub Kruzik pc->ops->setup = PCSetUp_Deflation; 87337eeb815SJakub Kruzik pc->ops->reset = PCReset_Deflation; 87437eeb815SJakub Kruzik pc->ops->destroy = PCDestroy_Deflation; 87537eeb815SJakub Kruzik pc->ops->setfromoptions = PCSetFromOptions_Deflation; 8768513960bSJakub Kruzik pc->ops->view = PCView_Deflation; 87737eeb815SJakub Kruzik pc->ops->applyrichardson = 0; 87837eeb815SJakub Kruzik pc->ops->applysymmetricleft = 0; 87937eeb815SJakub Kruzik pc->ops->applysymmetricright = 0; 88037eeb815SJakub Kruzik 88198d6e3deSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr); 882*859a873cSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr); 88339417d7eSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr); 884e662bc50SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr); 8853cf3a049SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr); 886e924b002SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr); 8874a99276eSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr); 888f3eaa4f0SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseKSP_C",PCDeflationSetCoarseKSP_Deflation);CHKERRQ(ierr); 88998d6e3deSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr); 89098d6e3deSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr); 89137eeb815SJakub Kruzik PetscFunctionReturn(0); 89237eeb815SJakub Kruzik } 89337eeb815SJakub Kruzik 894