xref: /petsc/src/ksp/pc/impls/hmg/hmg.c (revision b155ba7fa30d8622b9fa3568a5a1aefb65163000)
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 */
1149c604d5SFande Kong   PetscBool        subcoarsening;      /* If or not to use a subspace-based coarsening algorithm */
1249c604d5SFande Kong   PetscBool        usematmaij;         /* If or not to use MatMAIJ for saving memory */
1349c604d5SFande Kong   PetscInt         component;          /* Which subspace is used for the subspace-based coarsening algorithm? */
14360ee056SFande Kong } PC_HMG;
15360ee056SFande Kong 
16360ee056SFande Kong PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems*,PC);
17360ee056SFande Kong PetscErrorCode PCReset_MG(PC);
188a2c336bSFande Kong 
1949c604d5SFande Kong static PetscErrorCode PCHMGExtractSubMatrix_Private(Mat pmat,Mat *submat,MatReuse reuse,PetscInt component,PetscInt blocksize)
20360ee056SFande Kong {
21360ee056SFande Kong   IS             isrow;
22360ee056SFande Kong   PetscErrorCode ierr;
238a2c336bSFande Kong   PetscInt       rstart,rend;
24360ee056SFande Kong   MPI_Comm       comm;
25360ee056SFande Kong 
26360ee056SFande Kong   PetscFunctionBegin;
27360ee056SFande Kong   ierr = PetscObjectGetComm((PetscObject)pmat,&comm);CHKERRQ(ierr);
284fea3358SFande Kong   if (component>=blocksize) SETERRQ2(comm,PETSC_ERR_ARG_INCOMP,"Component %d should be less than block size %d \n",component,blocksize);
29360ee056SFande Kong   ierr = MatGetOwnershipRange(pmat,&rstart,&rend);CHKERRQ(ierr);
30360ee056SFande Kong   if ((rend-rstart)%blocksize != 0) SETERRQ3(comm,PETSC_ERR_ARG_INCOMP,"Block size %d is inconsisent for [%d, %d) \n",blocksize,rstart,rend);
3149c604d5SFande Kong   ierr = ISCreateStride(comm,(rend-rstart)/blocksize,rstart+component,blocksize,&isrow);
32360ee056SFande Kong   ierr = MatCreateSubMatrix(pmat,isrow,isrow,reuse,submat);CHKERRQ(ierr);
33360ee056SFande Kong   ierr = ISDestroy(&isrow);CHKERRQ(ierr);
34360ee056SFande Kong   PetscFunctionReturn(0);
35360ee056SFande Kong }
36360ee056SFande Kong 
378a2c336bSFande Kong static PetscErrorCode PCHMGExpandInterpolation_Private(Mat subinterp, Mat *interp, PetscInt blocksize)
38360ee056SFande Kong {
39360ee056SFande Kong   PetscInt              subrstart,subrend,subrowsize,subcolsize,subcstart,subcend,rowsize,colsize;
408a2c336bSFande Kong   PetscInt              subrow,row,nz,*d_nnz,*o_nnz,i,j,dnz,onz,max_nz,*indices;
418a2c336bSFande Kong   const PetscInt        *idx;
428a2c336bSFande Kong   const PetscScalar     *values;
43360ee056SFande Kong   PetscErrorCode        ierr;
448a2c336bSFande Kong   MPI_Comm              comm;
45360ee056SFande Kong 
46360ee056SFande Kong   PetscFunctionBegin;
478a2c336bSFande Kong   ierr = PetscObjectGetComm((PetscObject)subinterp,&comm);CHKERRQ(ierr);
488a2c336bSFande Kong   ierr = MatGetOwnershipRange(subinterp,&subrstart,&subrend);CHKERRQ(ierr);
498a2c336bSFande Kong   subrowsize = subrend-subrstart;
50360ee056SFande Kong   rowsize = subrowsize*blocksize;
51360ee056SFande Kong   ierr = PetscCalloc2(rowsize,&d_nnz,rowsize,&o_nnz);CHKERRQ(ierr);
528a2c336bSFande Kong   ierr = MatGetOwnershipRangeColumn(subinterp,&subcstart,&subcend);CHKERRQ(ierr);
538a2c336bSFande Kong   subcolsize = subcend - subcstart;
548a2c336bSFande Kong   colsize    = subcolsize*blocksize;
55360ee056SFande Kong   max_nz = 0;
568a2c336bSFande Kong   for (subrow=subrstart;subrow<subrend;subrow++) {
578a2c336bSFande Kong     ierr = MatGetRow(subinterp,subrow,&nz,&idx,NULL);CHKERRQ(ierr);
58360ee056SFande Kong     if (max_nz<nz) max_nz = nz;
59360ee056SFande Kong     dnz = 0; onz = 0;
60360ee056SFande Kong     for (i=0;i<nz;i++) {
618a2c336bSFande Kong       if(idx[i]>=subcstart && idx[i]<subcend) dnz++;
628a2c336bSFande Kong       else onz++;
63360ee056SFande Kong     }
64360ee056SFande Kong     for (i=0;i<blocksize;i++) {
65360ee056SFande Kong       d_nnz[(subrow-subrstart)*blocksize+i] = dnz;
66360ee056SFande Kong       o_nnz[(subrow-subrstart)*blocksize+i] = onz;
67360ee056SFande Kong     }
688a2c336bSFande Kong     ierr = MatRestoreRow(subinterp,subrow,&nz,&idx,NULL);CHKERRQ(ierr);
69360ee056SFande Kong   }
70360ee056SFande Kong   ierr = MatCreateAIJ(comm,rowsize,colsize,PETSC_DETERMINE,PETSC_DETERMINE,0,d_nnz,0,o_nnz,interp);CHKERRQ(ierr);
71360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
72360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
73360ee056SFande Kong   ierr = MatSetOption(*interp,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
74360ee056SFande Kong   ierr = MatSetFromOptions(*interp);CHKERRQ(ierr);
75360ee056SFande Kong 
76360ee056SFande Kong   ierr = MatSetUp(*interp);CHKERRQ(ierr);
77360ee056SFande Kong   ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
78071fcb05SBarry Smith   ierr = PetscMalloc1(max_nz,&indices);CHKERRQ(ierr);
798a2c336bSFande Kong   for (subrow=subrstart; subrow<subrend; subrow++) {
808a2c336bSFande Kong     ierr = MatGetRow(subinterp,subrow,&nz,&idx,&values);CHKERRQ(ierr);
81360ee056SFande Kong     for (i=0;i<blocksize;i++) {
82360ee056SFande Kong       row = subrow*blocksize+i;
83360ee056SFande Kong       for (j=0;j<nz;j++) {
84360ee056SFande Kong         indices[j] = idx[j]*blocksize+i;
85360ee056SFande Kong       }
86360ee056SFande Kong       ierr = MatSetValues(*interp,1,&row,nz,indices,values,INSERT_VALUES);CHKERRQ(ierr);
87360ee056SFande Kong     }
888a2c336bSFande Kong     ierr = MatRestoreRow(subinterp,subrow,&nz,&idx,&values);CHKERRQ(ierr);
89360ee056SFande Kong   }
90360ee056SFande Kong   ierr = PetscFree(indices);CHKERRQ(ierr);
91360ee056SFande Kong   ierr = MatAssemblyBegin(*interp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
92360ee056SFande Kong   ierr = MatAssemblyEnd(*interp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
93360ee056SFande Kong   PetscFunctionReturn(0);
94360ee056SFande Kong }
95360ee056SFande Kong 
96360ee056SFande Kong PetscErrorCode PCSetUp_HMG(PC pc)
97360ee056SFande Kong {
98360ee056SFande Kong   PetscErrorCode     ierr;
99360ee056SFande Kong   Mat                PA, submat;
100360ee056SFande Kong   PC_MG              *mg   = (PC_MG*)pc->data;
101360ee056SFande Kong   PC_HMG             *hmg   = (PC_HMG*) mg->innerctx;
102360ee056SFande Kong   MPI_Comm           comm;
103360ee056SFande Kong   PetscInt           level;
104360ee056SFande Kong   PetscInt           num_levels;
1058a2c336bSFande Kong   Mat                *operators,*interpolations;
1068a2c336bSFande Kong   PetscInt           blocksize;
107fd2dd295SFande Kong   const char         *prefix;
10807a4832bSFande Kong   PCMGGalerkinType   galerkin;
109360ee056SFande Kong 
110360ee056SFande Kong   PetscFunctionBegin;
111360ee056SFande Kong   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
112360ee056SFande Kong   if (pc->setupcalled) {
1135f36d8f2SFande Kong    if (hmg->reuseinterp) {
1145f36d8f2SFande Kong      /* If we did not use Galerkin in the last call or we have a different sparsity pattern now,
1155f36d8f2SFande Kong       * we have to build from scratch
11607a4832bSFande Kong       * */
11707a4832bSFande Kong      ierr = PCMGGetGalerkin(pc,&galerkin);CHKERRQ(ierr);
1185f36d8f2SFande Kong      if (galerkin == PC_MG_GALERKIN_NONE || pc->flag != SAME_NONZERO_PATTERN) pc->setupcalled = PETSC_FALSE;
119360ee056SFande Kong      ierr = PCMGSetGalerkin(pc,PC_MG_GALERKIN_PMAT);CHKERRQ(ierr);
120360ee056SFande Kong      ierr = PCSetUp_MG(pc);CHKERRQ(ierr);
121360ee056SFande Kong      PetscFunctionReturn(0);
122360ee056SFande Kong     } else {
123360ee056SFande Kong      ierr = PCReset_MG(pc);CHKERRQ(ierr);
124360ee056SFande Kong      pc->setupcalled = PETSC_FALSE;
125360ee056SFande Kong     }
126360ee056SFande Kong   }
127360ee056SFande Kong 
1288a2c336bSFande Kong   /* Create an inner PC (GAMG or HYPRE) */
1298a2c336bSFande Kong   if (!hmg->innerpc) {
1308a2c336bSFande Kong     ierr = PCCreate(comm,&hmg->innerpc);CHKERRQ(ierr);
131fd2dd295SFande Kong     /* If users do not set an inner pc type, we need to set a default value */
132fd2dd295SFande Kong     if (!hmg->innerpctype) {
133fd2dd295SFande Kong     /* If hypre is available, use hypre, otherwise, use gamg */
134fd2dd295SFande Kong #if PETSC_HAVE_HYPRE
135fd2dd295SFande Kong       ierr = PetscStrallocpy(PCHYPRE,&(hmg->innerpctype));CHKERRQ(ierr);
136fd2dd295SFande Kong #else
137fd2dd295SFande Kong       ierr = PetscStrallocpy(PCGAMG,&(hmg->innerpctype));CHKERRQ(ierr);
138fd2dd295SFande Kong #endif
1398a2c336bSFande Kong     }
140fd2dd295SFande Kong     ierr = PCSetType(hmg->innerpc,hmg->innerpctype);CHKERRQ(ierr);
141360ee056SFande Kong   }
142360ee056SFande Kong   ierr = PCGetOperators(pc,NULL,&PA);CHKERRQ(ierr);
1438a2c336bSFande Kong   /* Users need to correctly set a block size of matrix in order to use subspace coarsening */
1448a2c336bSFande Kong   ierr = MatGetBlockSize(PA,&blocksize);CHKERRQ(ierr);
1458a2c336bSFande Kong   if (blocksize<=1) hmg->subcoarsening = PETSC_FALSE;
1468a2c336bSFande Kong   /* Extract a submatrix for constructing subinterpolations */
1478a2c336bSFande Kong   if (hmg->subcoarsening) {
14849c604d5SFande Kong     ierr = PCHMGExtractSubMatrix_Private(PA,&submat,MAT_INITIAL_MATRIX,hmg->component,blocksize);CHKERRQ(ierr);
149360ee056SFande Kong     PA = submat;
150360ee056SFande Kong   }
1518a2c336bSFande Kong   ierr = PCSetOperators(hmg->innerpc,PA,PA);CHKERRQ(ierr);
1528a2c336bSFande Kong   if (hmg->subcoarsening) {
153360ee056SFande Kong    ierr = MatDestroy(&PA);CHKERRQ(ierr);
154360ee056SFande Kong   }
1558a2c336bSFande Kong   /* Setup inner PC correctly. During this step, matrix will be coarsened */
1568a2c336bSFande Kong   ierr = PCSetUseAmat(hmg->innerpc,PETSC_FALSE);CHKERRQ(ierr);
157fd2dd295SFande Kong   ierr = PetscObjectGetOptionsPrefix((PetscObject)pc,&prefix);CHKERRQ(ierr);
158fd2dd295SFande Kong   ierr = PetscObjectSetOptionsPrefix((PetscObject)hmg->innerpc,prefix);CHKERRQ(ierr);
159fd2dd295SFande Kong   ierr = PetscObjectAppendOptionsPrefix((PetscObject)hmg->innerpc,"hmg_inner_");CHKERRQ(ierr);
160fd2dd295SFande Kong   ierr = PCSetFromOptions(hmg->innerpc);CHKERRQ(ierr);
1618a2c336bSFande Kong   ierr = PCSetUp(hmg->innerpc);
162360ee056SFande Kong 
1638a2c336bSFande Kong   /* Obtain interpolations IN PLACE. For BoomerAMG, (I,J,data) is reused to avoid memory overhead */
164fd2dd295SFande Kong   ierr = PCGetInterpolations(hmg->innerpc,&num_levels,&interpolations);CHKERRQ(ierr);
1658a2c336bSFande Kong   /* We can reuse the coarse operators when we do the full space coarsening */
1668a2c336bSFande Kong   if (!hmg->subcoarsening) {
167fd2dd295SFande Kong     ierr = PCGetCoarseOperators(hmg->innerpc,&num_levels,&operators);CHKERRQ(ierr);
168360ee056SFande Kong   }
169360ee056SFande Kong 
1708a2c336bSFande Kong   ierr = PCDestroy(&hmg->innerpc);CHKERRQ(ierr);
1718a2c336bSFande Kong   hmg->innerpc = 0;
1728a2c336bSFande Kong   ierr = PCMGSetLevels_MG(pc,num_levels,NULL);CHKERRQ(ierr);
1738a2c336bSFande Kong   /* Set coarse matrices and interpolations to PCMG */
174360ee056SFande Kong   for (level=num_levels-1; level>0; level--) {
175360ee056SFande Kong     Mat P=0, pmat=0;
176360ee056SFande Kong     Vec b, x,r;
1778a2c336bSFande Kong     if (hmg->subcoarsening) {
1784bb91820SFande Kong       if (hmg->usematmaij) {
1794bb91820SFande Kong         ierr = MatCreateMAIJ(interpolations[level-1],blocksize,&P);CHKERRQ(ierr);
1804bb91820SFande Kong         ierr = MatDestroy(&interpolations[level-1]);CHKERRQ(ierr);
1814bb91820SFande Kong       } else {
1828a2c336bSFande Kong         /* Grow interpolation. In the future, we should use MAIJ */
1838a2c336bSFande Kong         ierr = PCHMGExpandInterpolation_Private(interpolations[level-1],&P,blocksize);CHKERRQ(ierr);
1848a2c336bSFande Kong         ierr = MatDestroy(&interpolations[level-1]);CHKERRQ(ierr);
1854bb91820SFande Kong       }
186360ee056SFande Kong     } else {
1878a2c336bSFande Kong       P = interpolations[level-1];
188360ee056SFande Kong     }
189360ee056SFande Kong     ierr = MatCreateVecs(P,&b,&r);CHKERRQ(ierr);
190360ee056SFande Kong     ierr = PCMGSetInterpolation(pc,level,P);CHKERRQ(ierr);
191360ee056SFande Kong     ierr = PCMGSetRestriction(pc,level,P);CHKERRQ(ierr);
192360ee056SFande Kong     ierr = MatDestroy(&P);CHKERRQ(ierr);
1938a2c336bSFande Kong     /* We reuse the matrices when we do not do subspace coarsening */
1948a2c336bSFande Kong     if ((level-1)>=0 && !hmg->subcoarsening) {
1958a2c336bSFande Kong       pmat = operators[level-1];
1968a2c336bSFande Kong       ierr = PCMGSetOperators(pc,level-1,pmat,pmat);CHKERRQ(ierr);
197360ee056SFande Kong       ierr = MatDestroy(&pmat);CHKERRQ(ierr);
198360ee056SFande Kong     }
199360ee056SFande Kong     ierr = PCMGSetRhs(pc,level-1,b);CHKERRQ(ierr);
200360ee056SFande Kong 
201360ee056SFande Kong     ierr = PCMGSetR(pc,level,r);CHKERRQ(ierr);
202360ee056SFande Kong     ierr = VecDestroy(&r);CHKERRQ(ierr);
203360ee056SFande Kong 
204fd2dd295SFande Kong     ierr = VecDuplicate(b,&x);CHKERRQ(ierr);
205360ee056SFande Kong     ierr = PCMGSetX(pc,level-1,x);CHKERRQ(ierr);
206360ee056SFande Kong     ierr = VecDestroy(&x);CHKERRQ(ierr);
207360ee056SFande Kong     ierr = VecDestroy(&b);CHKERRQ(ierr);
208360ee056SFande Kong   }
2098a2c336bSFande Kong   ierr = PetscFree(interpolations);CHKERRQ(ierr);
2108a2c336bSFande Kong   if (!hmg->subcoarsening) {
2118a2c336bSFande Kong     ierr = PetscFree(operators);CHKERRQ(ierr);
2128a2c336bSFande Kong   }
2138a2c336bSFande Kong   /* Turn Galerkin off when we already have coarse operators */
2148a2c336bSFande Kong   ierr = PCMGSetGalerkin(pc,hmg->subcoarsening ? PC_MG_GALERKIN_PMAT:PC_MG_GALERKIN_NONE);CHKERRQ(ierr);
215360ee056SFande Kong   ierr = PCSetDM(pc,NULL);CHKERRQ(ierr);
216360ee056SFande Kong   ierr = PCSetUseAmat(pc,PETSC_FALSE);CHKERRQ(ierr);
217360ee056SFande Kong   ierr = PetscObjectOptionsBegin((PetscObject)pc);CHKERRQ(ierr);
218360ee056SFande Kong   ierr = PCSetFromOptions_MG(PetscOptionsObject,pc);CHKERRQ(ierr); /* should be called in PCSetFromOptions_HMG(), but cannot be called prior to PCMGSetLevels() */
219360ee056SFande Kong   ierr = PetscOptionsEnd();CHKERRQ(ierr);
220360ee056SFande Kong   ierr = PCSetUp_MG(pc);CHKERRQ(ierr);
221360ee056SFande Kong   PetscFunctionReturn(0);
222360ee056SFande Kong }
223360ee056SFande Kong 
224360ee056SFande Kong PetscErrorCode PCDestroy_HMG(PC pc)
225360ee056SFande Kong {
226360ee056SFande Kong   PetscErrorCode ierr;
227360ee056SFande Kong   PC_MG          *mg  = (PC_MG*)pc->data;
2288a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
229360ee056SFande Kong 
230360ee056SFande Kong   PetscFunctionBegin;
2318a2c336bSFande Kong   ierr = PCDestroy(&hmg->innerpc);CHKERRQ(ierr);
2328a2c336bSFande Kong   ierr = PetscFree(hmg->innerpctype);CHKERRQ(ierr);
2338a2c336bSFande Kong   ierr = PetscFree(hmg);CHKERRQ(ierr);
234360ee056SFande Kong   ierr = PCDestroy_MG(pc);CHKERRQ(ierr);
235fd2dd295SFande Kong 
236fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",NULL);CHKERRQ(ierr);
237fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",NULL);CHKERRQ(ierr);
238fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",NULL);CHKERRQ(ierr);
239*b155ba7fSFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetCoarseningComponent_C",NULL);CHKERRQ(ierr);
240360ee056SFande Kong   PetscFunctionReturn(0);
241360ee056SFande Kong }
242360ee056SFande Kong 
243360ee056SFande Kong PetscErrorCode PCView_HMG(PC pc,PetscViewer viewer)
244360ee056SFande Kong {
245360ee056SFande Kong   PC_MG          *mg = (PC_MG*)pc->data;
2468a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
247360ee056SFande Kong   PetscErrorCode ierr;
248360ee056SFande Kong   PetscBool      iascii;
249360ee056SFande Kong 
250360ee056SFande Kong   PetscFunctionBegin;
251360ee056SFande Kong   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
252360ee056SFande Kong   if (iascii) {
2538a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Reuse interpolation: %s\n",hmg->reuseinterp? "true":"false");CHKERRQ(ierr);
2548a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Use subspace coarsening: %s\n",hmg->subcoarsening? "true":"false");CHKERRQ(ierr);
2554fea3358SFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Coarsening component: %d \n",hmg->component);CHKERRQ(ierr);
2564fea3358SFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Use MatMAIJ: %s \n",hmg->usematmaij? "true":"false");CHKERRQ(ierr);
2578a2c336bSFande Kong     ierr = PetscViewerASCIIPrintf(viewer," Inner PC type: %s \n",hmg->innerpctype);CHKERRQ(ierr);
258360ee056SFande Kong   }
259360ee056SFande Kong   ierr = PCView_MG(pc,viewer);CHKERRQ(ierr);
260360ee056SFande Kong   PetscFunctionReturn(0);
261360ee056SFande Kong }
262360ee056SFande Kong 
263360ee056SFande Kong PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems *PetscOptionsObject,PC pc)
264360ee056SFande Kong {
265360ee056SFande Kong   PetscErrorCode ierr;
266360ee056SFande Kong   PC_MG          *mg = (PC_MG*)pc->data;
2678a2c336bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
268360ee056SFande Kong 
269360ee056SFande Kong   PetscFunctionBegin;
270360ee056SFande Kong   ierr = PetscOptionsHead(PetscOptionsObject,"HMG");CHKERRQ(ierr);
271*b155ba7fSFande Kong   ierr = PetscOptionsBool("-pc_hmg_reuse_interpolation","Reuse the interpolation operators when possible (cheaper, weaker when matrix entries change a lot)","PCHMGSetReuseInterpolation",hmg->reuseinterp,&hmg->reuseinterp,NULL);CHKERRQ(ierr);
272*b155ba7fSFande Kong   ierr = PetscOptionsBool("-pc_hmg_use_subspace_coarsening","Use the subspace coarsening to compute the interpolations","PCHMGSetUseSubspaceCoarsening",hmg->subcoarsening,&hmg->subcoarsening,NULL);CHKERRQ(ierr);
273*b155ba7fSFande Kong   ierr = PetscOptionsBool("-pc_hmg_use_matmaij","Use MatMAIJ store interpolation for saving memory","PCHMGSetInnerPCType",hmg->usematmaij,&hmg->usematmaij,NULL);CHKERRQ(ierr);
274*b155ba7fSFande Kong   ierr = PetscOptionsInt("-pc_hmg_coarsening_component","Which component is chosen for the subspace-based coarsening algorithm","PCHMGSetCoarseningComponent",hmg->component,&hmg->component,NULL);CHKERRQ(ierr);
275360ee056SFande Kong   ierr = PetscOptionsTail();CHKERRQ(ierr);
276360ee056SFande Kong   PetscFunctionReturn(0);
277360ee056SFande Kong }
278360ee056SFande Kong 
279fd2dd295SFande Kong static PetscErrorCode PCHMGSetReuseInterpolation_HMG(PC pc, PetscBool reuse)
280fd2dd295SFande Kong {
28107a4832bSFande Kong   PC_MG          *mg  = (PC_MG*)pc->data;
28207a4832bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
283fd2dd295SFande Kong 
284fd2dd295SFande Kong   PetscFunctionBegin;
285fd2dd295SFande Kong   hmg->reuseinterp = reuse;
286fd2dd295SFande Kong   PetscFunctionReturn(0);
287fd2dd295SFande Kong }
288fd2dd295SFande Kong 
289*b155ba7fSFande Kong /*@
2908a2c336bSFande Kong    PCHMGSetReuseInterpolation - Reuse interpolation matrices in HMG
2918a2c336bSFande Kong 
2928a2c336bSFande Kong    Logically Collective on PC
2938a2c336bSFande Kong 
2948a2c336bSFande Kong    Input Parameters:
2958a2c336bSFande Kong +  pc - the HMG context
2968a2c336bSFande Kong -  reuse - True indicates that HMG will reuse the interpolations
2978a2c336bSFande Kong 
2988a2c336bSFande Kong    Options Database Keys:
29949c604d5SFande Kong .  -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time.
3008a2c336bSFande Kong 
3018a2c336bSFande Kong    Level: beginner
3028a2c336bSFande Kong 
3038a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, reuse, set
3048a2c336bSFande Kong 
3058a2c336bSFande Kong .seealso: PCHMG
306*b155ba7fSFande Kong @*/
3078a2c336bSFande Kong PetscErrorCode PCHMGSetReuseInterpolation(PC pc, PetscBool reuse)
3088a2c336bSFande Kong {
309fd2dd295SFande Kong   PetscErrorCode ierr;
310fd2dd295SFande Kong 
311fd2dd295SFande Kong   PetscFunctionBegin;
312fd2dd295SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
313fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetReuseInterpolation_C",(PC,PetscBool),(pc,reuse));CHKERRQ(ierr);
314fd2dd295SFande Kong   PetscFunctionReturn(0);
315fd2dd295SFande Kong }
316fd2dd295SFande Kong 
317fd2dd295SFande Kong static PetscErrorCode PCHMGSetUseSubspaceCoarsening_HMG(PC pc, PetscBool subspace)
318fd2dd295SFande Kong {
31907a4832bSFande Kong   PC_MG          *mg  = (PC_MG*)pc->data;
32007a4832bSFande Kong   PC_HMG         *hmg = (PC_HMG*) mg->innerctx;
3218a2c336bSFande Kong 
3228a2c336bSFande Kong   PetscFunctionBegin;
323fd2dd295SFande Kong   hmg->subcoarsening = subspace;
3248a2c336bSFande Kong   PetscFunctionReturn(0);
3258a2c336bSFande Kong }
3268a2c336bSFande Kong 
327*b155ba7fSFande Kong /*@
3288a2c336bSFande Kong    PCHMGSetUseSubspaceCoarsening - Use subspace coarsening in HMG
3298a2c336bSFande Kong 
3308a2c336bSFande Kong    Logically Collective on PC
3318a2c336bSFande Kong 
3328a2c336bSFande Kong    Input Parameters:
3338a2c336bSFande Kong +  pc - the HMG context
3348a2c336bSFande Kong -  reuse - True indicates that HMG will use the subspace coarsening
3358a2c336bSFande Kong 
3368a2c336bSFande Kong    Options Database Keys:
33749c604d5SFande Kong .  -pc_hmg_use_subspace_coarsening  <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix).
3388a2c336bSFande Kong 
3398a2c336bSFande Kong    Level: beginner
3408a2c336bSFande Kong 
3418a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, subspace, coarsening
3428a2c336bSFande Kong 
3438a2c336bSFande Kong .seealso: PCHMG
344*b155ba7fSFande Kong @*/
3458a2c336bSFande Kong PetscErrorCode PCHMGSetUseSubspaceCoarsening(PC pc, PetscBool subspace)
3468a2c336bSFande Kong {
347fd2dd295SFande Kong   PetscErrorCode ierr;
3488a2c336bSFande Kong 
3498a2c336bSFande Kong   PetscFunctionBegin;
3508a2c336bSFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
351fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetUseSubspaceCoarsening_C",(PC,PetscBool),(pc,subspace));CHKERRQ(ierr);
352fd2dd295SFande Kong   PetscFunctionReturn(0);
353fd2dd295SFande Kong }
354fd2dd295SFande Kong 
355fd2dd295SFande Kong static PetscErrorCode PCHMGSetInnerPCType_HMG(PC pc, PCType type)
356fd2dd295SFande Kong {
35707a4832bSFande Kong   PC_MG           *mg  = (PC_MG*)pc->data;
35807a4832bSFande Kong   PC_HMG          *hmg = (PC_HMG*) mg->innerctx;
359fd2dd295SFande Kong   PetscErrorCode  ierr;
360fd2dd295SFande Kong 
361fd2dd295SFande Kong   PetscFunctionBegin;
362fd2dd295SFande Kong   ierr = PetscStrallocpy(type,&(hmg->innerpctype));CHKERRQ(ierr);
3638a2c336bSFande Kong   PetscFunctionReturn(0);
3648a2c336bSFande Kong }
3658a2c336bSFande Kong 
366*b155ba7fSFande Kong /*@C
3678a2c336bSFande Kong    PCHMGSetInnerPCType - Set an inner PC type
3688a2c336bSFande Kong 
3698a2c336bSFande Kong    Logically Collective on PC
3708a2c336bSFande Kong 
3718a2c336bSFande Kong    Input Parameters:
3728a2c336bSFande Kong +  pc - the HMG context
3738a2c336bSFande Kong -  type - <hypre, gamg> coarsening algorithm
3748a2c336bSFande Kong 
3758a2c336bSFande Kong    Options Database Keys:
37649c604d5SFande Kong .  -hmg_inner_pc_type <hypre, gamg> - What method is used to coarsen matrix
3778a2c336bSFande Kong 
3788a2c336bSFande Kong    Level: beginner
3798a2c336bSFande Kong 
3808a2c336bSFande Kong .keywords: HMG, multigrid, interpolation, coarsening
3818a2c336bSFande Kong 
3828a2c336bSFande Kong .seealso: PCHMG, PCType
383*b155ba7fSFande Kong @*/
3848a2c336bSFande Kong PetscErrorCode PCHMGSetInnerPCType(PC pc, PCType type)
3858a2c336bSFande Kong {
3868a2c336bSFande Kong   PetscErrorCode  ierr;
3878a2c336bSFande Kong 
3888a2c336bSFande Kong   PetscFunctionBegin;
3898a2c336bSFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
390fd2dd295SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetInnerPCType_C",(PC,PCType),(pc,type));CHKERRQ(ierr);
3918a2c336bSFande Kong   PetscFunctionReturn(0);
3928a2c336bSFande Kong }
3938a2c336bSFande Kong 
39449c604d5SFande Kong static PetscErrorCode PCHMGSetCoarseningComponent_HMG(PC pc, PetscInt component)
39549c604d5SFande Kong {
39649c604d5SFande Kong   PC_MG           *mg  = (PC_MG*)pc->data;
39749c604d5SFande Kong   PC_HMG          *hmg = (PC_HMG*) mg->innerctx;
39849c604d5SFande Kong 
39949c604d5SFande Kong   PetscFunctionBegin;
40049c604d5SFande Kong   hmg->component = component;
40149c604d5SFande Kong   PetscFunctionReturn(0);
40249c604d5SFande Kong }
40349c604d5SFande Kong 
404*b155ba7fSFande Kong /*@
40549c604d5SFande Kong    PCHMGSetCoarseningComponent - Set which component is used for the subspace-based coarsening algorithm
40649c604d5SFande Kong 
40749c604d5SFande Kong    Logically Collective on PC
40849c604d5SFande Kong 
40949c604d5SFande Kong    Input Parameters:
41049c604d5SFande Kong +  pc - the HMG context
41149c604d5SFande Kong -  component - which component PC will coarsen
41249c604d5SFande Kong 
41349c604d5SFande Kong    Options Database Keys:
41449c604d5SFande Kong .  -pc_hmg_coarsening_component - Which component is chosen for the subspace-based coarsening algorithm
41549c604d5SFande Kong 
41649c604d5SFande Kong    Level: beginner
41749c604d5SFande Kong 
41849c604d5SFande Kong .keywords: HMG, multigrid, interpolation, coarsening, component
41949c604d5SFande Kong 
42049c604d5SFande Kong .seealso: PCHMG, PCType
421*b155ba7fSFande Kong @*/
42249c604d5SFande Kong PetscErrorCode PCHMGSetCoarseningComponent(PC pc, PetscInt component)
42349c604d5SFande Kong {
42449c604d5SFande Kong   PetscErrorCode  ierr;
42549c604d5SFande Kong 
42649c604d5SFande Kong   PetscFunctionBegin;
42749c604d5SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
42849c604d5SFande Kong   ierr = PetscUseMethod(pc,"PCHMGSetCoarseningComponent_C",(PC,PetscInt),(pc,component));CHKERRQ(ierr);
42949c604d5SFande Kong   PetscFunctionReturn(0);
43049c604d5SFande Kong }
43149c604d5SFande Kong 
43249c604d5SFande Kong static PetscErrorCode PCHMGUseMatMAIJ_HMG(PC pc, PetscBool usematmaij)
43349c604d5SFande Kong {
43449c604d5SFande Kong   PC_MG           *mg  = (PC_MG*)pc->data;
43549c604d5SFande Kong   PC_HMG          *hmg = (PC_HMG*) mg->innerctx;
43649c604d5SFande Kong 
43749c604d5SFande Kong   PetscFunctionBegin;
43849c604d5SFande Kong   hmg->usematmaij = usematmaij;
43949c604d5SFande Kong   PetscFunctionReturn(0);
44049c604d5SFande Kong }
44149c604d5SFande Kong 
442*b155ba7fSFande Kong /*@
44349c604d5SFande Kong    PCHMGUseMatMAIJ - Set a flag that indicates if or not to use MatMAIJ for interpolations for saving memory
44449c604d5SFande Kong 
44549c604d5SFande Kong    Logically Collective on PC
44649c604d5SFande Kong 
44749c604d5SFande Kong    Input Parameters:
44849c604d5SFande Kong +  pc - the HMG context
44949c604d5SFande Kong -  usematmaij - if or not to use MatMAIJ for interpolations. By default, it is true for saving memory
45049c604d5SFande Kong 
45149c604d5SFande Kong    Options Database Keys:
45249c604d5SFande Kong .  -pc_hmg_use_matmaij - <true | false >
45349c604d5SFande Kong 
45449c604d5SFande Kong    Level: beginner
45549c604d5SFande Kong 
45649c604d5SFande Kong .keywords: HMG, multigrid, interpolation, coarsening, MatMAIJ
45749c604d5SFande Kong 
45849c604d5SFande Kong .seealso: PCHMG, PCType
459*b155ba7fSFande Kong @*/
46049c604d5SFande Kong PetscErrorCode PCHMGUseMatMAIJ(PC pc, PetscBool usematmaij)
46149c604d5SFande Kong {
46249c604d5SFande Kong   PetscErrorCode  ierr;
46349c604d5SFande Kong 
46449c604d5SFande Kong   PetscFunctionBegin;
46549c604d5SFande Kong   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
46649c604d5SFande Kong   ierr = PetscUseMethod(pc,"PCHMGUseMatMAIJ_C",(PC,PetscBool),(pc,usematmaij));CHKERRQ(ierr);
46749c604d5SFande Kong   PetscFunctionReturn(0);
46849c604d5SFande Kong }
46949c604d5SFande Kong 
4708a2c336bSFande Kong /*MC
471fd2dd295SFande Kong    PCHMG - Hybrid of PETSc preconditioners (such as ASM, BJacobi, SOR, etc.) and Hypre BoomerAMG, GAMG or other multilevel methods. BoomerAMG, GAMG
472fd2dd295SFande Kong            or other multilevel methods is used to coarsen matrix and generate a sequence of coarse matrices and interpolations. The matrices and
473fd2dd295SFande Kong            interpolations are employed to construct PCMG, and then any available PETSc preconditioners can be chosen as smoothers and the coarse solver.
474360ee056SFande Kong 
475360ee056SFande Kong    Options Database Keys:
4768a2c336bSFande Kong +  -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time.
4778a2c336bSFande Kong .  -pc_hmg_use_subspace_coarsening  <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix).
478fd2dd295SFande Kong .  -hmg_inner_pc_type <hypre, gamg, ...> - What method is used to coarsen matrix
4794bb91820SFande Kong -  -pc_hmg_use_matmaij <true | false> - Whether or not to use MatMAIJ for multicomponent problems for saving memory
480360ee056SFande Kong 
481360ee056SFande Kong 
482360ee056SFande Kong    Notes:
483360ee056SFande Kong     For multicomponent problems, we can just coarsen one submatrix associated with one particular component. In this way, the preconditioner setup
484360ee056SFande Kong     time is significantly reduced. One typical use case is neutron transport equations. There are many variables on each mesh vertex due to the
485360ee056SFande Kong     of angle and energy. Each variable, in fact, corresponds to the same PDEs but with different material properties.
486360ee056SFande Kong 
487360ee056SFande Kong    Level: beginner
488360ee056SFande Kong 
4898a2c336bSFande Kong    Concepts: Hybrid of ASM and MG, Subspace Coarsening
490360ee056SFande Kong 
491360ee056SFande Kong     References:
49249c604d5SFande 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
493360ee056SFande Kong     Newton-Krylov-Schwarz method with subspace-based coarsening and partition-based balancing for the multigroup neutron transport equations on
494360ee056SFande Kong     3D unstructured meshes, arXiv preprint arXiv:1903.03659, 2019
495360ee056SFande Kong 
496fd2dd295SFande Kong .seealso:  PCCreate(), PCSetType(), PCType, PC, PCMG, PCHYPRE, PCHMG, PCGetCoarseOperators(), PCGetInterpolations(), PCHMGSetReuseInterpolation(), PCHMGSetUseSubspaceCoarsening(),
497fd2dd295SFande Kong            PCHMGSetInnerPCType()
498360ee056SFande Kong 
499360ee056SFande Kong M*/
500360ee056SFande Kong PETSC_EXTERN PetscErrorCode PCCreate_HMG(PC pc)
501360ee056SFande Kong {
502360ee056SFande Kong   PetscErrorCode ierr;
503360ee056SFande Kong   PC_HMG         *hmg;
504360ee056SFande Kong   PC_MG          *mg;
505360ee056SFande Kong 
506360ee056SFande Kong   PetscFunctionBegin;
507360ee056SFande Kong   /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */
508360ee056SFande Kong   if (pc->ops->destroy) {
509360ee056SFande Kong     ierr =  (*pc->ops->destroy)(pc);CHKERRQ(ierr);
510360ee056SFande Kong     pc->data = 0;
511360ee056SFande Kong   }
512360ee056SFande Kong   ierr = PetscFree(((PetscObject)pc)->type_name);CHKERRQ(ierr);
513360ee056SFande Kong 
514360ee056SFande Kong   ierr = PCSetType(pc,PCMG);CHKERRQ(ierr);
515645b8336SFande Kong   ierr = PetscObjectChangeTypeName((PetscObject)pc, PCHMG);CHKERRQ(ierr);
516fd2dd295SFande Kong   ierr = PetscNew(&hmg);CHKERRQ(ierr);
517360ee056SFande Kong 
518360ee056SFande Kong   mg                      = (PC_MG*) pc->data;
519360ee056SFande Kong   mg->innerctx            = hmg;
520360ee056SFande Kong   hmg->reuseinterp        = PETSC_FALSE;
5218a2c336bSFande Kong   hmg->subcoarsening      = PETSC_FALSE;
5224bb91820SFande Kong   hmg->usematmaij         = PETSC_TRUE;
52349c604d5SFande Kong   hmg->component          = 0;
5248a2c336bSFande Kong   hmg->innerpc            = NULL;
525360ee056SFande Kong 
526360ee056SFande Kong   pc->ops->setfromoptions = PCSetFromOptions_HMG;
527360ee056SFande Kong   pc->ops->view           = PCView_HMG;
528360ee056SFande Kong   pc->ops->destroy        = PCDestroy_HMG;
529360ee056SFande Kong   pc->ops->setup          = PCSetUp_HMG;
530fd2dd295SFande Kong 
531fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",PCHMGSetReuseInterpolation_HMG);CHKERRQ(ierr);
532fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",PCHMGSetUseSubspaceCoarsening_HMG);CHKERRQ(ierr);
533fd2dd295SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",PCHMGSetInnerPCType_HMG);CHKERRQ(ierr);
53449c604d5SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetCoarseningComponent_C",PCHMGSetCoarseningComponent_HMG);CHKERRQ(ierr);
53549c604d5SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHMGUseMatMAIJ_C",PCHMGUseMatMAIJ_HMG);CHKERRQ(ierr);
536360ee056SFande Kong   PetscFunctionReturn(0);
537360ee056SFande Kong }
538