xref: /petsc/src/ksp/pc/impls/hmg/hmg.c (revision fd2dd29587ccae96583179f094812ea051599fc0)
1360ee056SFande Kong #include <petscdm.h>
2360ee056SFande Kong #include <petscctable.h>
3360ee056SFande Kong #include <petsc/private/matimpl.h>
4360ee056SFande Kong #include <petsc/private/pcmgimpl.h>
5360ee056SFande Kong #include <petsc/private/pcimpl.h>      /*I "petscpc.h" I*/
6360ee056SFande Kong 
7360ee056SFande Kong typedef struct {
88a2c336bSFande Kong   PC               innerpc;            /* A MG inner PC (Hypre or PCGAMG) to setup interpolations and coarse operators  */
98a2c336bSFande Kong   char*            innerpctype;        /* PCGAMG or PCHYPRE */
108a2c336bSFande Kong   PetscBool        reuseinterp;        /* A flag indicates if or not to reuse the interpolations */
118a2c336bSFande Kong   PetscBool        subcoarsening;
12360ee056SFande Kong } PC_HMG;
13360ee056SFande Kong 
14360ee056SFande Kong PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems*,PC);
15360ee056SFande Kong PetscErrorCode PCReset_MG(PC);
168a2c336bSFande Kong 
178a2c336bSFande Kong static PetscErrorCode PCHMGExtractSubMatrix_Private(Mat pmat,Mat *submat,MatReuse reuse,PetscInt blocksize)
18360ee056SFande Kong {
19360ee056SFande Kong   IS             isrow;
20360ee056SFande Kong   PetscErrorCode ierr;
218a2c336bSFande Kong   PetscInt       rstart,rend;
22360ee056SFande Kong   MPI_Comm       comm;
23360ee056SFande Kong 
24360ee056SFande Kong   PetscFunctionBegin;
25360ee056SFande Kong   ierr = PetscObjectGetComm((PetscObject)pmat,&comm);CHKERRQ(ierr);
26360ee056SFande Kong   ierr = MatGetOwnershipRange(pmat,&rstart,&rend);CHKERRQ(ierr);
27360ee056SFande Kong   if ((rend-rstart)%blocksize != 0) SETERRQ3(comm,PETSC_ERR_ARG_INCOMP,"Block size %d is inconsisent for [%d, %d) \n",blocksize,rstart,rend);
288a2c336bSFande Kong   ierr = ISCreateStride(comm,(rend-rstart)/blocksize,rstart,blocksize,&isrow);
29360ee056SFande Kong   ierr = MatCreateSubMatrix(pmat,isrow,isrow,reuse,submat);CHKERRQ(ierr);
30360ee056SFande Kong   ierr = ISDestroy(&isrow);CHKERRQ(ierr);
31360ee056SFande Kong   PetscFunctionReturn(0);
32360ee056SFande Kong }
33360ee056SFande Kong 
348a2c336bSFande Kong static PetscErrorCode PCHMGExpandInterpolation_Private(Mat subinterp, Mat *interp, PetscInt blocksize)
35360ee056SFande Kong {
36360ee056SFande Kong   PetscInt              subrstart,subrend,subrowsize,subcolsize,subcstart,subcend,rowsize,colsize;
378a2c336bSFande Kong   PetscInt              subrow,row,nz,*d_nnz,*o_nnz,i,j,dnz,onz,max_nz,*indices;
388a2c336bSFande Kong   const PetscInt        *idx;
398a2c336bSFande Kong   const PetscScalar     *values;
40360ee056SFande Kong   PetscErrorCode        ierr;
418a2c336bSFande Kong   MPI_Comm              comm;
42360ee056SFande Kong 
43360ee056SFande Kong   PetscFunctionBegin;
448a2c336bSFande Kong   ierr = PetscObjectGetComm((PetscObject)subinterp,&comm);CHKERRQ(ierr);
458a2c336bSFande Kong   ierr = MatGetOwnershipRange(subinterp,&subrstart,&subrend);CHKERRQ(ierr);
468a2c336bSFande Kong   subrowsize = subrend-subrstart;
47360ee056SFande Kong   rowsize = subrowsize*blocksize;
48360ee056SFande Kong   ierr = PetscCalloc2(rowsize,&d_nnz,rowsize,&o_nnz);CHKERRQ(ierr);
498a2c336bSFande Kong   ierr = MatGetOwnershipRangeColumn(subinterp,&subcstart,&subcend);CHKERRQ(ierr);
508a2c336bSFande Kong   subcolsize = subcend - subcstart;
518a2c336bSFande Kong   colsize    = subcolsize*blocksize;
52360ee056SFande Kong   max_nz = 0;
538a2c336bSFande Kong   for (subrow=subrstart;subrow<subrend;subrow++) {
548a2c336bSFande Kong     ierr = MatGetRow(subinterp,subrow,&nz,&idx,NULL);CHKERRQ(ierr);
55360ee056SFande Kong     if (max_nz<nz) max_nz = nz;
56360ee056SFande Kong     dnz = 0; onz = 0;
57360ee056SFande Kong     for (i=0;i<nz;i++) {
588a2c336bSFande Kong       if(idx[i]>=subcstart && idx[i]<subcend) dnz++;
598a2c336bSFande Kong       else onz++;
60360ee056SFande Kong     }
61360ee056SFande Kong     for (i=0;i<blocksize;i++) {
62360ee056SFande Kong       d_nnz[(subrow-subrstart)*blocksize+i] = dnz;
63360ee056SFande Kong       o_nnz[(subrow-subrstart)*blocksize+i] = onz;
64360ee056SFande Kong     }
658a2c336bSFande Kong     ierr = MatRestoreRow(subinterp,subrow,&nz,&idx,NULL);CHKERRQ(ierr);
66360ee056SFande Kong   }
67360ee056SFande Kong   ierr = MatCreateAIJ(comm,rowsize,colsize,PETSC_DETERMINE,PETSC_DETERMINE,0,d_nnz,0,o_nnz,interp);CHKERRQ(ierr);
68360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
69360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
70360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
71360ee056SFande Kong   ierr = MatSetFromOptions(*interp);CHKERRQ(ierr);
72360ee056SFande Kong 
73360ee056SFande Kong   ierr = MatSetUp(*interp);CHKERRQ(ierr);
74360ee056SFande Kong   ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
75360ee056SFande Kong   ierr = PetscCalloc1(max_nz,&indices);CHKERRQ(ierr);
768a2c336bSFande Kong   for (subrow=subrstart; subrow<subrend; subrow++) {
778a2c336bSFande Kong     ierr = MatGetRow(subinterp,subrow,&nz,&idx,&values);CHKERRQ(ierr);
78360ee056SFande Kong     for (i=0;i<blocksize;i++) {
79360ee056SFande Kong       row = subrow*blocksize+i;
80360ee056SFande Kong       for (j=0;j<nz;j++) {
81360ee056SFande Kong         indices[j] = idx[j]*blocksize+i;
82360ee056SFande Kong       }
83360ee056SFande Kong       ierr = MatSetValues(*interp,1,&row,nz,indices,values,INSERT_VALUES);CHKERRQ(ierr);
84360ee056SFande Kong     }
858a2c336bSFande Kong     ierr = MatRestoreRow(subinterp,subrow,&nz,&idx,&values);CHKERRQ(ierr);
86360ee056SFande Kong   }
87360ee056SFande Kong   ierr = PetscFree(indices);CHKERRQ(ierr);
88360ee056SFande Kong   ierr = MatAssemblyBegin(*interp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89360ee056SFande Kong   ierr = MatAssemblyEnd(*interp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
90360ee056SFande Kong   PetscFunctionReturn(0);
91360ee056SFande Kong }
92360ee056SFande Kong 
93360ee056SFande Kong PetscErrorCode PCSetUp_HMG(PC pc)
94360ee056SFande Kong {
95360ee056SFande Kong   PetscErrorCode     ierr;
96360ee056SFande Kong   Mat                PA, submat;
97360ee056SFande Kong   PC_MG              *mg   = (PC_MG*)pc->data;
98360ee056SFande Kong   PC_HMG             *hmg   = (PC_HMG*) mg->innerctx;
99360ee056SFande Kong   MPI_Comm           comm;
100360ee056SFande Kong   PetscInt           level;
101360ee056SFande Kong   PetscInt           num_levels;
1028a2c336bSFande Kong   Mat                *operators,*interpolations;
1038a2c336bSFande Kong   PetscInt           blocksize;
104*fd2dd295SFande Kong   const char         *prefix;
105360ee056SFande Kong 
106360ee056SFande Kong   PetscFunctionBegin;
107360ee056SFande Kong   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
108360ee056SFande Kong   if (pc->setupcalled) {
1098a2c336bSFande Kong    /* Only reuse interpolations when nonzero pattern does not change */
110360ee056SFande Kong    if (pc->flag == SAME_NONZERO_PATTERN && hmg->reuseinterp) {
111360ee056SFande Kong      ierr = PCMGSetGalerkin(pc,PC_MG_GALERKIN_PMAT);CHKERRQ(ierr);
112360ee056SFande Kong      ierr = PCSetUp_MG(pc);CHKERRQ(ierr);
113360ee056SFande Kong      PetscFunctionReturn(0);
114360ee056SFande Kong     } else {
115360ee056SFande Kong      ierr = PCReset_MG(pc);CHKERRQ(ierr);
116360ee056SFande Kong      pc->setupcalled = PETSC_FALSE;
117360ee056SFande Kong     }
118360ee056SFande Kong   }
119360ee056SFande Kong 
1208a2c336bSFande Kong   /* Create an inner PC (GAMG or HYPRE) */
1218a2c336bSFande Kong   if (!hmg->innerpc) {
1228a2c336bSFande Kong     ierr = PCCreate(comm,&hmg->innerpc);CHKERRQ(ierr);
123*fd2dd295SFande Kong     /* If users do not set an inner pc type, we need to set a default value */
124*fd2dd295SFande Kong     if (!hmg->innerpctype) {
125*fd2dd295SFande Kong     /* If hypre is available, use hypre, otherwise, use gamg */
126*fd2dd295SFande Kong #if PETSC_HAVE_HYPRE
127*fd2dd295SFande Kong       ierr = PetscStrallocpy(PCHYPRE,&(hmg->innerpctype));CHKERRQ(ierr);
128*fd2dd295SFande Kong #else
129*fd2dd295SFande Kong       ierr = PetscStrallocpy(PCGAMG,&(hmg->innerpctype));CHKERRQ(ierr);
130*fd2dd295SFande Kong #endif
1318a2c336bSFande Kong     }
132*fd2dd295SFande Kong     ierr = PCSetType(hmg->innerpc,hmg->innerpctype);CHKERRQ(ierr);
133360ee056SFande Kong   }
134360ee056SFande Kong   ierr = PCGetOperators(pc,NULL,&PA);CHKERRQ(ierr);
1358a2c336bSFande Kong   /* Users need to correctly set a block size of matrix in order to use subspace coarsening */
1368a2c336bSFande Kong   ierr = MatGetBlockSize(PA,&blocksize);CHKERRQ(ierr);
1378a2c336bSFande Kong   if (blocksize<=1) hmg->subcoarsening = PETSC_FALSE;
1388a2c336bSFande Kong   /* Extract a submatrix for constructing subinterpolations */
1398a2c336bSFande Kong   if (hmg->subcoarsening) {
1408a2c336bSFande Kong     ierr = PCHMGExtractSubMatrix_Private(PA,&submat,MAT_INITIAL_MATRIX,blocksize);CHKERRQ(ierr);
141360ee056SFande Kong     PA = submat;
142360ee056SFande Kong   }
1438a2c336bSFande Kong   ierr = PCSetOperators(hmg->innerpc,PA,PA);CHKERRQ(ierr);
1448a2c336bSFande Kong   if (hmg->subcoarsening) {
145360ee056SFande Kong    ierr = MatDestroy(&PA);CHKERRQ(ierr);
146360ee056SFande Kong   }
1478a2c336bSFande Kong   /* Setup inner PC correctly. During this step, matrix will be coarsened */
1488a2c336bSFande Kong   ierr = PCSetUseAmat(hmg->innerpc,PETSC_FALSE);CHKERRQ(ierr);
149*fd2dd295SFande Kong   ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,&prefix);CHKERRQ(ierr);
150*fd2dd295SFande Kong   ierr = PetscObjectSetOptionsPrefix((PetscObject)hmg->innerpc,prefix);CHKERRQ(ierr);
151*fd2dd295SFande Kong   ierr = PetscObjectAppendOptionsPrefix((PetscObject)hmg->innerpc,"hmg_inner_");CHKERRQ(ierr);
152*fd2dd295SFande Kong   ierr = PCSetFromOptions(hmg->innerpc);CHKERRQ(ierr);
1538a2c336bSFande Kong   ierr = PCSetUp(hmg->innerpc);
154360ee056SFande Kong 
1558a2c336bSFande Kong   /* Obtain interpolations IN PLACE. For BoomerAMG, (I,J,data) is reused to avoid memory overhead */
156*fd2dd295SFande Kong   ierr = PCGetInterpolations(hmg->innerpc,&num_levels,&interpolations);CHKERRQ(ierr);
1578a2c336bSFande Kong   /* We can reuse the coarse operators when we do the full space coarsening */
1588a2c336bSFande Kong   if (!hmg->subcoarsening) {
159*fd2dd295SFande Kong     ierr = PCGetCoarseOperators(hmg->innerpc,&num_levels,&operators);CHKERRQ(ierr);
160360ee056SFande Kong   }
161360ee056SFande Kong 
1628a2c336bSFande Kong   ierr = PCDestroy(&hmg->innerpc);CHKERRQ(ierr);
1638a2c336bSFande Kong   hmg->innerpc = 0;
1648a2c336bSFande Kong   ierr = PCMGSetLevels_MG(pc,num_levels,NULL);CHKERRQ(ierr);
1658a2c336bSFande Kong   /* Set coarse matrices and interpolations to PCMG */
166360ee056SFande Kong   for (level=num_levels-1; level>0; level--) {
167360ee056SFande Kong     Mat P=0, pmat=0;
168360ee056SFande Kong     Vec b, x,r;
1698a2c336bSFande Kong     if (hmg->subcoarsening) {
1708a2c336bSFande Kong       /* Grow interpolation. In the future, we should use MAIJ */
1718a2c336bSFande Kong       ierr = PCHMGExpandInterpolation_Private(interpolations[level-1],&P,blocksize);CHKERRQ(ierr);
1728a2c336bSFande Kong       ierr = MatDestroy(&interpolations[level-1]);CHKERRQ(ierr);
173360ee056SFande Kong     } else {
1748a2c336bSFande Kong       P = interpolations[level-1];
175360ee056SFande Kong     }
176360ee056SFande Kong     ierr = MatCreateVecs(P,&b,&r);CHKERRQ(ierr);
177360ee056SFande Kong     ierr = PCMGSetInterpolation(pc,level,P);CHKERRQ(ierr);
178360ee056SFande Kong     ierr = PCMGSetRestriction(pc,level,P);CHKERRQ(ierr);
179360ee056SFande Kong     ierr = MatDestroy(&P);CHKERRQ(ierr);
1808a2c336bSFande Kong     /* We reuse the matrices when we do not do subspace coarsening */
1818a2c336bSFande Kong     if ((level-1)>=0 && !hmg->subcoarsening) {
1828a2c336bSFande Kong       pmat = operators[level-1];
1838a2c336bSFande Kong       ierr = PCMGSetOperators(pc,level-1,pmat,pmat);CHKERRQ(ierr);
184360ee056SFande Kong       ierr = MatDestroy(&pmat);CHKERRQ(ierr);
185360ee056SFande Kong     }
186360ee056SFande Kong     ierr = PCMGSetRhs(pc,level-1,b);CHKERRQ(ierr);
187360ee056SFande Kong 
188360ee056SFande Kong     ierr = PCMGSetR(pc,level,r);CHKERRQ(ierr);
189360ee056SFande Kong     ierr = VecDestroy(&r);CHKERRQ(ierr);
190360ee056SFande Kong 
191*fd2dd295SFande Kong     ierr = VecDuplicate(b,&x);CHKERRQ(ierr);
192360ee056SFande Kong     ierr = PCMGSetX(pc,level-1,x);CHKERRQ(ierr);
193360ee056SFande Kong     ierr = VecDestroy(&x);CHKERRQ(ierr);
194360ee056SFande Kong     ierr = VecDestroy(&b);CHKERRQ(ierr);
195360ee056SFande Kong   }
1968a2c336bSFande Kong   ierr = PetscFree(interpolations);CHKERRQ(ierr);
1978a2c336bSFande Kong   if (!hmg->subcoarsening) {
1988a2c336bSFande Kong     ierr = PetscFree(operators);CHKERRQ(ierr);
1998a2c336bSFande Kong   }
2008a2c336bSFande Kong   /* Turn Galerkin off when we already have coarse operators */
2018a2c336bSFande Kong   ierr = PCMGSetGalerkin(pc,hmg->subcoarsening ? PC_MG_GALERKIN_PMAT:PC_MG_GALERKIN_NONE);CHKERRQ(ierr);
202360ee056SFande Kong   ierr = PCSetDM(pc,NULL);CHKERRQ(ierr);
203360ee056SFande Kong   ierr = PCSetUseAmat(pc,PETSC_FALSE);CHKERRQ(ierr);
204360ee056SFande Kong   ierr = PetscObjectOptionsBegin((PetscObject)pc);CHKERRQ(ierr);
205360ee056SFande Kong   ierr = PCSetFromOptions_MG(PetscOptionsObject,pc);CHKERRQ(ierr); /* should be called in PCSetFromOptions_HMG(), but cannot be called prior to PCMGSetLevels() */
206360ee056SFande Kong   ierr = PetscOptionsEnd();CHKERRQ(ierr);
207360ee056SFande Kong   ierr = PCSetUp_MG(pc);CHKERRQ(ierr);
208360ee056SFande Kong   PetscFunctionReturn(0);
209360ee056SFande Kong }
210360ee056SFande Kong 
211360ee056SFande Kong PetscErrorCode PCDestroy_HMG(PC pc)
212360ee056SFande Kong {
213360ee056SFande Kong   PetscErrorCode ierr;
214360ee056SFande Kong   PC_MG          *mg  = (PC_MG*)pc->data;
2158a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
216360ee056SFande Kong 
217360ee056SFande Kong   PetscFunctionBegin;
2188a2c336bSFande Kong   ierr = PCDestroy(&hmg->innerpc);CHKERRQ(ierr);
2198a2c336bSFande Kong   ierr = PetscFree(hmg->innerpctype);CHKERRQ(ierr);
2208a2c336bSFande Kong   ierr = PetscFree(hmg);CHKERRQ(ierr);
221360ee056SFande Kong   ierr = PCDestroy_MG(pc);CHKERRQ(ierr);
222*fd2dd295SFande Kong 
223*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",NULL);CHKERRQ(ierr);
224*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",NULL);CHKERRQ(ierr);
225*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",NULL);CHKERRQ(ierr);
226360ee056SFande Kong   PetscFunctionReturn(0);
227360ee056SFande Kong }
228360ee056SFande Kong 
229360ee056SFande Kong PetscErrorCode PCView_HMG(PC pc,PetscViewer viewer)
230360ee056SFande Kong {
231360ee056SFande Kong   PC_MG          *mg = (PC_MG*)pc->data;
2328a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
233360ee056SFande Kong   PetscErrorCode ierr;
234360ee056SFande Kong   PetscBool      iascii;
235360ee056SFande Kong 
236360ee056SFande Kong   PetscFunctionBegin;
237360ee056SFande Kong   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
238360ee056SFande Kong   if (iascii) {
2398a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Reuse interpolation: %s\n",hmg->reuseinterp? "true":"false");CHKERRQ(ierr);
2408a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Use subspace coarsening: %s\n",hmg->subcoarsening? "true":"false");CHKERRQ(ierr);
2418a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Inner PC type: %s \n",hmg->innerpctype);CHKERRQ(ierr);
242360ee056SFande Kong   }
243360ee056SFande Kong   ierr = PCView_MG(pc,viewer);CHKERRQ(ierr);
244360ee056SFande Kong   PetscFunctionReturn(0);
245360ee056SFande Kong }
246360ee056SFande Kong 
247360ee056SFande Kong PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems *PetscOptionsObject,PC pc)
248360ee056SFande Kong {
249360ee056SFande Kong   PetscErrorCode ierr;
250360ee056SFande Kong   PC_MG          *mg = (PC_MG*)pc->data;
2518a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
252360ee056SFande Kong 
253360ee056SFande Kong   PetscFunctionBegin;
254360ee056SFande Kong   ierr = PetscOptionsHead(PetscOptionsObject,"HMG");CHKERRQ(ierr);
2558a2c336bSFande Kong   ierr = PetscOptionsBool("-pc_hmg_reuse_interpolation","Reuse the interpolation operators when possible (cheaper, weaker when matrix entries change a lot)","None",hmg->reuseinterp,&hmg->reuseinterp,NULL);CHKERRQ(ierr);
2568a2c336bSFande Kong   ierr = PetscOptionsBool("-pc_hmg_use_subspace_coarsening","Use the subspace coarsening to compute the interpolations","None",hmg->subcoarsening,&hmg->subcoarsening,NULL);CHKERRQ(ierr);
257360ee056SFande Kong   ierr = PetscOptionsTail();CHKERRQ(ierr);
258360ee056SFande Kong   PetscFunctionReturn(0);
259360ee056SFande Kong }
260360ee056SFande Kong 
261*fd2dd295SFande Kong static PetscErrorCode PCHMGSetReuseInterpolation_HMG(PC pc, PetscBool reuse)
262*fd2dd295SFande Kong {
263*fd2dd295SFande Kong   PC_MG          *mg;
264*fd2dd295SFande Kong   PC_HMG         *hmg;
265*fd2dd295SFande Kong 
266*fd2dd295SFande Kong   PetscFunctionBegin;
267*fd2dd295SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
268*fd2dd295SFande Kong   mg = (PC_MG*)pc->data;
269*fd2dd295SFande Kong   hmg = (PC_HMG*) mg->innerctx;
270*fd2dd295SFande Kong   hmg->reuseinterp = reuse;
271*fd2dd295SFande Kong   PetscFunctionReturn(0);
272*fd2dd295SFande Kong }
273*fd2dd295SFande Kong 
274360ee056SFande Kong /*MC
2758a2c336bSFande Kong    PCHMGSetReuseInterpolation - Reuse interpolation matrices in HMG
2768a2c336bSFande Kong 
2778a2c336bSFande Kong    Logically Collective on PC
2788a2c336bSFande Kong 
2798a2c336bSFande Kong    Input Parameters:
2808a2c336bSFande Kong +  pc - the HMG context
2818a2c336bSFande Kong -  reuse - True indicates that HMG will reuse the interpolations
2828a2c336bSFande Kong 
2838a2c336bSFande Kong    Options Database Keys:
2848a2c336bSFande Kong +  -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time.
2858a2c336bSFande Kong 
2868a2c336bSFande Kong    Level: beginner
2878a2c336bSFande Kong 
2888a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, reuse, set
2898a2c336bSFande Kong 
2908a2c336bSFande Kong .seealso: PCHMG
2918a2c336bSFande Kong M*/
2928a2c336bSFande Kong PetscErrorCode PCHMGSetReuseInterpolation(PC pc, PetscBool reuse)
2938a2c336bSFande Kong {
294*fd2dd295SFande Kong   PetscErrorCode ierr;
295*fd2dd295SFande Kong 
296*fd2dd295SFande Kong   PetscFunctionBegin;
297*fd2dd295SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
298*fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetReuseInterpolation_C",(PC,PetscBool),(pc,reuse));CHKERRQ(ierr);
299*fd2dd295SFande Kong   PetscFunctionReturn(0);
300*fd2dd295SFande Kong }
301*fd2dd295SFande Kong 
302*fd2dd295SFande Kong static PetscErrorCode PCHMGSetUseSubspaceCoarsening_HMG(PC pc, PetscBool subspace)
303*fd2dd295SFande Kong {
3048a2c336bSFande Kong   PC_MG          *mg;
3058a2c336bSFande Kong   PC_HMG         *hmg;
3068a2c336bSFande Kong 
3078a2c336bSFande Kong   PetscFunctionBegin;
3088a2c336bSFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3098a2c336bSFande Kong   mg = (PC_MG*)pc->data;
3108a2c336bSFande Kong   hmg = (PC_HMG*) mg->innerctx;
311*fd2dd295SFande Kong   hmg->subcoarsening = subspace;
3128a2c336bSFande Kong   PetscFunctionReturn(0);
3138a2c336bSFande Kong }
3148a2c336bSFande Kong 
3158a2c336bSFande Kong /*MC
3168a2c336bSFande Kong    PCHMGSetUseSubspaceCoarsening - Use subspace coarsening in HMG
3178a2c336bSFande Kong 
3188a2c336bSFande Kong    Logically Collective on PC
3198a2c336bSFande Kong 
3208a2c336bSFande Kong    Input Parameters:
3218a2c336bSFande Kong +  pc - the HMG context
3228a2c336bSFande Kong -  reuse - True indicates that HMG will use the subspace coarsening
3238a2c336bSFande Kong 
3248a2c336bSFande Kong    Options Database Keys:
3258a2c336bSFande Kong +  -pc_hmg_use_subspace_coarsening  <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix).
3268a2c336bSFande Kong 
3278a2c336bSFande Kong    Level: beginner
3288a2c336bSFande Kong 
3298a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, subspace, coarsening
3308a2c336bSFande Kong 
3318a2c336bSFande Kong .seealso: PCHMG
3328a2c336bSFande Kong M*/
3338a2c336bSFande Kong PetscErrorCode PCHMGSetUseSubspaceCoarsening(PC pc, PetscBool subspace)
3348a2c336bSFande Kong {
335*fd2dd295SFande Kong   PetscErrorCode ierr;
3368a2c336bSFande Kong 
3378a2c336bSFande Kong   PetscFunctionBegin;
3388a2c336bSFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
339*fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetUseSubspaceCoarsening_C",(PC,PetscBool),(pc,subspace));CHKERRQ(ierr);
340*fd2dd295SFande Kong   PetscFunctionReturn(0);
341*fd2dd295SFande Kong }
342*fd2dd295SFande Kong 
343*fd2dd295SFande Kong static PetscErrorCode PCHMGSetInnerPCType_HMG(PC pc, PCType type)
344*fd2dd295SFande Kong {
345*fd2dd295SFande Kong   PC_MG           *mg;
346*fd2dd295SFande Kong   PC_HMG          *hmg;
347*fd2dd295SFande Kong   PetscErrorCode  ierr;
348*fd2dd295SFande Kong 
349*fd2dd295SFande Kong   PetscFunctionBegin;
350*fd2dd295SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
351*fd2dd295SFande Kong   PetscValidPointer(type,2);
3528a2c336bSFande Kong   mg = (PC_MG*)pc->data;
3538a2c336bSFande Kong   hmg = (PC_HMG*) mg->innerctx;
354*fd2dd295SFande Kong   ierr = PetscStrallocpy(type,&(hmg->innerpctype));CHKERRQ(ierr);
3558a2c336bSFande Kong   PetscFunctionReturn(0);
3568a2c336bSFande Kong }
3578a2c336bSFande Kong 
3588a2c336bSFande Kong /*MC
3598a2c336bSFande Kong    PCHMGSetInnerPCType - Set an inner PC type
3608a2c336bSFande Kong 
3618a2c336bSFande Kong    Logically Collective on PC
3628a2c336bSFande Kong 
3638a2c336bSFande Kong    Input Parameters:
3648a2c336bSFande Kong +  pc - the HMG context
3658a2c336bSFande Kong -  type - <hypre, gamg> coarsening algorithm
3668a2c336bSFande Kong 
3678a2c336bSFande Kong    Options Database Keys:
368*fd2dd295SFande Kong +  -hmg_inner_pc_type <hypre, gamg> - What method is used to coarsen matrix
3698a2c336bSFande Kong 
3708a2c336bSFande Kong    Level: beginner
3718a2c336bSFande Kong 
3728a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, coarsening
3738a2c336bSFande Kong 
3748a2c336bSFande Kong .seealso: PCHMG, PCType
3758a2c336bSFande Kong M*/
3768a2c336bSFande Kong PetscErrorCode PCHMGSetInnerPCType(PC pc, PCType type)
3778a2c336bSFande Kong {
3788a2c336bSFande Kong   PetscErrorCode  ierr;
3798a2c336bSFande Kong 
3808a2c336bSFande Kong   PetscFunctionBegin;
3818a2c336bSFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
382*fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetInnerPCType_C",(PC,PCType),(pc,type));CHKERRQ(ierr);
3838a2c336bSFande Kong   PetscFunctionReturn(0);
3848a2c336bSFande Kong }
3858a2c336bSFande Kong 
3868a2c336bSFande Kong /*MC
387*fd2dd295SFande Kong    PCHMG - Hybrid of PETSc preconditioners (such as ASM, BJacobi, SOR, etc.) and Hypre BoomerAMG, GAMG or other multilevel methods. BoomerAMG, GAMG
388*fd2dd295SFande Kong            or other multilevel methods is used to coarsen matrix and generate a sequence of coarse matrices and interpolations. The matrices and
389*fd2dd295SFande Kong            interpolations are employed to construct PCMG, and then any available PETSc preconditioners can be chosen as smoothers and the coarse solver.
390360ee056SFande Kong 
391360ee056SFande Kong    Options Database Keys:
3928a2c336bSFande Kong +  -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time.
3938a2c336bSFande Kong .  -pc_hmg_use_subspace_coarsening  <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix).
394*fd2dd295SFande Kong .  -hmg_inner_pc_type <hypre, gamg, ...> - What method is used to coarsen matrix
395360ee056SFande Kong 
396360ee056SFande Kong 
397360ee056SFande Kong    Notes:
398360ee056SFande Kong     For multicomponent problems, we can just coarsen one submatrix associated with one particular component. In this way, the preconditioner setup
399360ee056SFande Kong     time is significantly reduced. One typical use case is neutron transport equations. There are many variables on each mesh vertex due to the
400360ee056SFande Kong     of angle and energy. Each variable, in fact, corresponds to the same PDEs but with different material properties.
401360ee056SFande Kong 
402360ee056SFande Kong    Level: beginner
403360ee056SFande Kong 
4048a2c336bSFande Kong    Concepts: Hybrid of ASM and MG, Subspace Coarsening
405360ee056SFande Kong 
406360ee056SFande Kong     References:
407360ee056SFande Kong +   1. - Fande Kong, Yaqi Wang, Derek R Gaston, Cody J Permann, Andrew E Slaughter, Alexander D Lindsay, Richard C Martineau, A highly parallel multilevel
408360ee056SFande Kong     Newton-Krylov-Schwarz method with subspace-based coarsening and partition-based balancing for the multigroup neutron transport equations on
409360ee056SFande Kong     3D unstructured meshes, arXiv preprint arXiv:1903.03659, 2019
410360ee056SFande Kong 
411*fd2dd295SFande Kong .seealso:  PCCreate(), PCSetType(), PCType, PC, PCMG, PCHYPRE, PCHMG, PCGetCoarseOperators(), PCGetInterpolations(), PCHMGSetReuseInterpolation(), PCHMGSetUseSubspaceCoarsening(),
412*fd2dd295SFande Kong            PCHMGSetInnerPCType()
413360ee056SFande Kong 
414360ee056SFande Kong M*/
415360ee056SFande Kong PETSC_EXTERN PetscErrorCode PCCreate_HMG(PC pc)
416360ee056SFande Kong {
417360ee056SFande Kong   PetscErrorCode ierr;
418360ee056SFande Kong   PC_HMG         *hmg;
419360ee056SFande Kong   PC_MG          *mg;
420360ee056SFande Kong 
421360ee056SFande Kong   PetscFunctionBegin;
422360ee056SFande Kong   /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */
423360ee056SFande Kong   if (pc->ops->destroy) {
424360ee056SFande Kong     ierr =  (*pc->ops->destroy)(pc);CHKERRQ(ierr);
425360ee056SFande Kong     pc->data = 0;
426360ee056SFande Kong   }
427360ee056SFande Kong   ierr = PetscFree(((PetscObject)pc)->type_name);CHKERRQ(ierr);
428360ee056SFande Kong 
429360ee056SFande Kong   ierr = PCSetType(pc,PCMG);CHKERRQ(ierr);
430*fd2dd295SFande Kong   ierr = PetscNew(&hmg);CHKERRQ(ierr);
431360ee056SFande Kong 
432360ee056SFande Kong   mg                      = (PC_MG*) pc->data;
433360ee056SFande Kong   mg->innerctx            = hmg;
434360ee056SFande Kong   hmg->reuseinterp        = PETSC_FALSE;
4358a2c336bSFande Kong   hmg->subcoarsening      = PETSC_FALSE;
4368a2c336bSFande Kong   hmg->innerpc            = NULL;
437360ee056SFande Kong 
438360ee056SFande Kong   pc->ops->setfromoptions = PCSetFromOptions_HMG;
439360ee056SFande Kong   pc->ops->view           = PCView_HMG;
440360ee056SFande Kong   pc->ops->destroy        = PCDestroy_HMG;
441360ee056SFande Kong   pc->ops->setup          = PCSetUp_HMG;
442*fd2dd295SFande Kong 
443*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",PCHMGSetReuseInterpolation_HMG);CHKERRQ(ierr);
444*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",PCHMGSetUseSubspaceCoarsening_HMG);CHKERRQ(ierr);
445*fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",PCHMGSetInnerPCType_HMG);CHKERRQ(ierr);
446360ee056SFande Kong   PetscFunctionReturn(0);
447360ee056SFande Kong }
448