xref: /petsc/src/ksp/pc/impls/redundant/redundant.c (revision 3f9fe4453ac6fcef10788d326c676dfc3fb403b0)
1dba47a55SKris Buschelman #define PETSCKSP_DLL
2dba47a55SKris Buschelman 
34b9ad928SBarry Smith /*
43f457be1SHong Zhang   This file defines a "solve the problem redundantly on each subgroup of processor" preconditioner.
54b9ad928SBarry Smith */
66356e834SBarry Smith #include "private/pcimpl.h"     /*I "petscpc.h" I*/
74b9ad928SBarry Smith #include "petscksp.h"
84b9ad928SBarry Smith 
94b9ad928SBarry Smith typedef struct {
103e065800SHong Zhang   KSP          ksp;
114b9ad928SBarry Smith   PC           pc;                   /* actual preconditioner used on each processor */
127adad957SLisandro Dalcin   Vec          xsub,ysub;            /* vectors of a subcommunicator to hold parallel vectors of ((PetscObject)pc)->comm */
133f457be1SHong Zhang   Vec          xdup,ydup;            /* parallel vector that congregates xsub or ysub facilitating vector scattering */
14b3804887SHong Zhang   Mat          pmats;                /* matrix and optional preconditioner matrix belong to a subcommunicator */
153f457be1SHong Zhang   VecScatter   scatterin,scatterout; /* scatter used to move all values to each processor group (subcommunicator) */
164b9ad928SBarry Smith   PetscTruth   useparallelmat;
17c540e29cSHong Zhang   PetscSubcomm psubcomm;
181fbd8f88SHong Zhang   PetscInt     nsubcomm;           /* num of data structure PetscSubcomm */
194b9ad928SBarry Smith } PC_Redundant;
204b9ad928SBarry Smith 
214b9ad928SBarry Smith #undef __FUNCT__
224b9ad928SBarry Smith #define __FUNCT__ "PCView_Redundant"
236849ba73SBarry Smith static PetscErrorCode PCView_Redundant(PC pc,PetscViewer viewer)
244b9ad928SBarry Smith {
254b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
26dfbe8321SBarry Smith   PetscErrorCode ierr;
2732077d6dSBarry Smith   PetscTruth     iascii,isstring;
2803ccd0b4SBarry Smith   PetscViewer    subviewer;
294b9ad928SBarry Smith 
304b9ad928SBarry Smith   PetscFunctionBegin;
312692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
322692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
3332077d6dSBarry Smith   if (iascii) {
3403ccd0b4SBarry Smith     if (!red->psubcomm) {
3503ccd0b4SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Redundant preconditioner: Not yet setup\n");CHKERRQ(ierr);
3603ccd0b4SBarry Smith     } else {
373e065800SHong Zhang       ierr = PetscViewerASCIIPrintf(viewer,"  Redundant preconditioner: First (color=0) of %D PCs follows\n",red->nsubcomm);CHKERRQ(ierr);
387adad957SLisandro Dalcin       ierr = PetscViewerGetSubcomm(viewer,((PetscObject)red->pc)->comm,&subviewer);CHKERRQ(ierr);
3903ccd0b4SBarry Smith       if (red->psubcomm->color) { /* only view first redundant pc */
404b9ad928SBarry Smith 	ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
413e065800SHong Zhang 	ierr = KSPView(red->ksp,subviewer);CHKERRQ(ierr);
424b9ad928SBarry Smith 	ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
434b9ad928SBarry Smith       }
447adad957SLisandro Dalcin       ierr = PetscViewerRestoreSubcomm(viewer,((PetscObject)red->pc)->comm,&subviewer);CHKERRQ(ierr);
454b9ad928SBarry Smith     }
4603ccd0b4SBarry Smith   } else if (isstring) {
4703ccd0b4SBarry Smith     ierr = PetscViewerStringSPrintf(viewer," Redundant solver preconditioner");CHKERRQ(ierr);
484b9ad928SBarry Smith   } else {
4965e19b50SBarry Smith     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PC redundant",((PetscObject)viewer)->type_name);
504b9ad928SBarry Smith   }
514b9ad928SBarry Smith   PetscFunctionReturn(0);
524b9ad928SBarry Smith }
534b9ad928SBarry Smith 
544b9ad928SBarry Smith #undef __FUNCT__
554b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_Redundant"
566849ba73SBarry Smith static PetscErrorCode PCSetUp_Redundant(PC pc)
574b9ad928SBarry Smith {
584b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
59dfbe8321SBarry Smith   PetscErrorCode ierr;
6045fc02eaSBarry Smith   PetscInt       mstart,mend,mlocal,m,mlocal_sub,rstart_sub,rend_sub,mloc_sub;
6113f74950SBarry Smith   PetscMPIInt    size;
624b9ad928SBarry Smith   MatReuse       reuse = MAT_INITIAL_MATRIX;
634b9ad928SBarry Smith   MatStructure   str = DIFFERENT_NONZERO_PATTERN;
647adad957SLisandro Dalcin   MPI_Comm       comm = ((PetscObject)pc)->comm,subcomm;
6523ce1328SBarry Smith   Vec            vec;
663f457be1SHong Zhang   PetscMPIInt    subsize,subrank;
671fbd8f88SHong Zhang   const char     *prefix;
68b862ddfaSBarry Smith   const PetscInt *range;
693f457be1SHong Zhang 
704b9ad928SBarry Smith   PetscFunctionBegin;
7123ce1328SBarry Smith   ierr = MatGetVecs(pc->pmat,&vec,0);CHKERRQ(ierr);
7223ce1328SBarry Smith   ierr = VecGetSize(vec,&m);CHKERRQ(ierr);
731fbd8f88SHong Zhang 
744b9ad928SBarry Smith   if (!pc->setupcalled) {
755f06b7aaSBarry Smith     if (!red->psubcomm) {
761fbd8f88SHong Zhang       ierr = PetscSubcommCreate(comm,red->nsubcomm,&red->psubcomm);CHKERRQ(ierr);
771fbd8f88SHong Zhang       ierr = PetscLogObjectMemory(pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
781fbd8f88SHong Zhang 
791fbd8f88SHong Zhang       /* create a new PC that processors in each subcomm have copy of */
800d7810c8SBarry Smith       subcomm = red->psubcomm->comm;
815f06b7aaSBarry Smith       ierr = KSPCreate(subcomm,&red->ksp);CHKERRQ(ierr);
825f06b7aaSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)red->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
835f06b7aaSBarry Smith       ierr = PetscLogObjectParent(pc,red->ksp);CHKERRQ(ierr);
845f06b7aaSBarry Smith       ierr = KSPSetType(red->ksp,KSPPREONLY);CHKERRQ(ierr);
855f06b7aaSBarry Smith       ierr = KSPGetPC(red->ksp,&red->pc);CHKERRQ(ierr);
86cf52b8b1SHong Zhang       ierr = PCSetType(red->pc,PCLU);CHKERRQ(ierr);
87cf52b8b1SHong Zhang 
881fbd8f88SHong Zhang       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
895f06b7aaSBarry Smith       ierr = KSPSetOptionsPrefix(red->ksp,prefix);CHKERRQ(ierr);
905f06b7aaSBarry Smith       ierr = KSPAppendOptionsPrefix(red->ksp,"redundant_");CHKERRQ(ierr);
915f06b7aaSBarry Smith     } else {
925f06b7aaSBarry Smith        subcomm = red->psubcomm->comm;
935f06b7aaSBarry Smith     }
941fbd8f88SHong Zhang 
953f457be1SHong Zhang     /* create working vectors xsub/ysub and xdup/ydup */
9623ce1328SBarry Smith     ierr = VecGetLocalSize(vec,&mlocal);CHKERRQ(ierr);
973f457be1SHong Zhang     ierr = VecGetOwnershipRange(vec,&mstart,&mend);CHKERRQ(ierr);
984b9ad928SBarry Smith 
993f457be1SHong Zhang     /* get local size of xsub/ysub */
1001fbd8f88SHong Zhang     ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr);
1011fbd8f88SHong Zhang     ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr);
102b862ddfaSBarry Smith     ierr = MatGetOwnershipRanges(pc->pmat,&range);CHKERRQ(ierr);
103b862ddfaSBarry Smith     rstart_sub = range[red->psubcomm->n*subrank]; /* rstart in xsub/ysub */
1043f457be1SHong Zhang     if (subrank+1 < subsize){
105b862ddfaSBarry Smith       rend_sub = range[red->psubcomm->n*(subrank+1)];
1063f457be1SHong Zhang     } else {
1073f457be1SHong Zhang       rend_sub = m;
1083f457be1SHong Zhang     }
1093f457be1SHong Zhang     mloc_sub = rend_sub - rstart_sub;
1101fbd8f88SHong Zhang     ierr = VecCreateMPI(subcomm,mloc_sub,PETSC_DECIDE,&red->ysub);CHKERRQ(ierr);
1113f457be1SHong Zhang     /* create xsub with empty local arrays, because xdup's arrays will be placed into it */
1121fbd8f88SHong Zhang     ierr = VecCreateMPIWithArray(subcomm,mloc_sub,PETSC_DECIDE,PETSC_NULL,&red->xsub);CHKERRQ(ierr);
1133f457be1SHong Zhang 
1143f457be1SHong Zhang     /* create xdup and ydup. ydup has empty local arrays because ysub's arrays will be place into it.
1157adad957SLisandro Dalcin        Note: we use communicator dupcomm, not ((PetscObject)pc)->comm! */
1161fbd8f88SHong Zhang     ierr = VecCreateMPI(red->psubcomm->dupparent,mloc_sub,PETSC_DECIDE,&red->xdup);CHKERRQ(ierr);
1171fbd8f88SHong Zhang     ierr = VecCreateMPIWithArray(red->psubcomm->dupparent,mloc_sub,PETSC_DECIDE,PETSC_NULL,&red->ydup);CHKERRQ(ierr);
1183f457be1SHong Zhang 
1193f457be1SHong Zhang     /* create vec scatters */
1203f457be1SHong Zhang     if (!red->scatterin){
1213f457be1SHong Zhang       IS       is1,is2;
1223f457be1SHong Zhang       PetscInt *idx1,*idx2,i,j,k;
12345fc02eaSBarry Smith 
1241d79065fSBarry Smith       ierr = PetscMalloc2(red->psubcomm->n*mlocal,PetscInt,&idx1,red->psubcomm->n*mlocal,PetscInt,&idx2);CHKERRQ(ierr);
1253f457be1SHong Zhang       j = 0;
1261fbd8f88SHong Zhang       for (k=0; k<red->psubcomm->n; k++){
1273f457be1SHong Zhang         for (i=mstart; i<mend; i++){
1283f457be1SHong Zhang           idx1[j]   = i;
1293f457be1SHong Zhang           idx2[j++] = i + m*k;
1303f457be1SHong Zhang         }
1313f457be1SHong Zhang       }
1321fbd8f88SHong Zhang       ierr = ISCreateGeneral(comm,red->psubcomm->n*mlocal,idx1,&is1);CHKERRQ(ierr);
1331fbd8f88SHong Zhang       ierr = ISCreateGeneral(comm,red->psubcomm->n*mlocal,idx2,&is2);CHKERRQ(ierr);
1343f457be1SHong Zhang       ierr = VecScatterCreate(vec,is1,red->xdup,is2,&red->scatterin);CHKERRQ(ierr);
1353f457be1SHong Zhang       ierr = ISDestroy(is1);CHKERRQ(ierr);
1363f457be1SHong Zhang       ierr = ISDestroy(is2);CHKERRQ(ierr);
1373f457be1SHong Zhang 
1381fbd8f88SHong Zhang       ierr = ISCreateStride(comm,mlocal,mstart+ red->psubcomm->color*m,1,&is1);CHKERRQ(ierr);
1393f457be1SHong Zhang       ierr = ISCreateStride(comm,mlocal,mstart,1,&is2);CHKERRQ(ierr);
1403f457be1SHong Zhang       ierr = VecScatterCreate(red->xdup,is1,vec,is2,&red->scatterout);CHKERRQ(ierr);
1413f457be1SHong Zhang       ierr = ISDestroy(is1);CHKERRQ(ierr);
1423f457be1SHong Zhang       ierr = ISDestroy(is2);CHKERRQ(ierr);
1431d79065fSBarry Smith       ierr = PetscFree2(idx1,idx2);CHKERRQ(ierr);
1444b9ad928SBarry Smith     }
1454b9ad928SBarry Smith   }
14623ce1328SBarry Smith   ierr = VecDestroy(vec);CHKERRQ(ierr);
1474b9ad928SBarry Smith 
1484b9ad928SBarry Smith   /* if pmatrix set by user is sequential then we do not need to gather the parallel matrix */
1493f457be1SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1504b9ad928SBarry Smith   if (size == 1) {
1514b9ad928SBarry Smith     red->useparallelmat = PETSC_FALSE;
1524b9ad928SBarry Smith   }
1534b9ad928SBarry Smith 
1544b9ad928SBarry Smith   if (red->useparallelmat) {
1554b9ad928SBarry Smith     if (pc->setupcalled == 1 && pc->flag == DIFFERENT_NONZERO_PATTERN) {
1564b9ad928SBarry Smith       /* destroy old matrices */
1574b9ad928SBarry Smith       if (red->pmats) {
158b3804887SHong Zhang         ierr = MatDestroy(red->pmats);CHKERRQ(ierr);
1594b9ad928SBarry Smith       }
1604b9ad928SBarry Smith     } else if (pc->setupcalled == 1) {
1614b9ad928SBarry Smith       reuse = MAT_REUSE_MATRIX;
1624b9ad928SBarry Smith       str   = SAME_NONZERO_PATTERN;
1634b9ad928SBarry Smith     }
1644b9ad928SBarry Smith 
1653f457be1SHong Zhang     /* grab the parallel matrix and put it into processors of a subcomminicator */
166f664ae05SHong Zhang     /*--------------------------------------------------------------------------*/
167f664ae05SHong Zhang     ierr = VecGetLocalSize(red->ysub,&mlocal_sub);CHKERRQ(ierr);
16869db28dcSHong Zhang     ierr = MatGetRedundantMatrix(pc->pmat,red->psubcomm->n,red->psubcomm->comm,mlocal_sub,reuse,&red->pmats);CHKERRQ(ierr);
1693f457be1SHong Zhang     /* tell PC of the subcommunicator its operators */
17090f1c854SHong Zhang     ierr = KSPSetOperators(red->ksp,red->pmats,red->pmats,str);CHKERRQ(ierr);
1714b9ad928SBarry Smith   } else {
17290f1c854SHong Zhang     ierr = KSPSetOperators(red->ksp,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr);
1734b9ad928SBarry Smith   }
1740c24e6a1SHong Zhang   if (pc->setfromoptionscalled){
1753e065800SHong Zhang     ierr = KSPSetFromOptions(red->ksp);CHKERRQ(ierr);
1760c24e6a1SHong Zhang   }
1773e065800SHong Zhang   ierr = KSPSetUp(red->ksp);CHKERRQ(ierr);
1784b9ad928SBarry Smith   PetscFunctionReturn(0);
1794b9ad928SBarry Smith }
1804b9ad928SBarry Smith 
1814b9ad928SBarry Smith #undef __FUNCT__
1824b9ad928SBarry Smith #define __FUNCT__ "PCApply_Redundant"
1836849ba73SBarry Smith static PetscErrorCode PCApply_Redundant(PC pc,Vec x,Vec y)
1844b9ad928SBarry Smith {
1854b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
186dfbe8321SBarry Smith   PetscErrorCode ierr;
1873f457be1SHong Zhang   PetscScalar    *array;
1884b9ad928SBarry Smith 
1894b9ad928SBarry Smith   PetscFunctionBegin;
1903f457be1SHong Zhang   /* scatter x to xdup */
191ca9f406cSSatish Balay   ierr = VecScatterBegin(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192ca9f406cSSatish Balay   ierr = VecScatterEnd(red->scatterin,x,red->xdup,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1933f457be1SHong Zhang 
1943f457be1SHong Zhang   /* place xdup's local array into xsub */
1953f457be1SHong Zhang   ierr = VecGetArray(red->xdup,&array);CHKERRQ(ierr);
1963f457be1SHong Zhang   ierr = VecPlaceArray(red->xsub,(const PetscScalar*)array);CHKERRQ(ierr);
1974b9ad928SBarry Smith 
1984b9ad928SBarry Smith   /* apply preconditioner on each processor */
1993f457be1SHong Zhang   ierr = PCApply(red->pc,red->xsub,red->ysub);CHKERRQ(ierr);
2003f457be1SHong Zhang   ierr = VecResetArray(red->xsub);CHKERRQ(ierr);
2013f457be1SHong Zhang   ierr = VecRestoreArray(red->xdup,&array);CHKERRQ(ierr);
2024b9ad928SBarry Smith 
2033f457be1SHong Zhang   /* place ysub's local array into ydup */
2043f457be1SHong Zhang   ierr = VecGetArray(red->ysub,&array);CHKERRQ(ierr);
2053f457be1SHong Zhang   ierr = VecPlaceArray(red->ydup,(const PetscScalar*)array);CHKERRQ(ierr);
2063f457be1SHong Zhang 
2073f457be1SHong Zhang   /* scatter ydup to y */
208ca9f406cSSatish Balay   ierr = VecScatterBegin(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209ca9f406cSSatish Balay   ierr = VecScatterEnd(red->scatterout,red->ydup,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2103f457be1SHong Zhang   ierr = VecResetArray(red->ydup);CHKERRQ(ierr);
2113f457be1SHong Zhang   ierr = VecRestoreArray(red->ysub,&array);CHKERRQ(ierr);
2124b9ad928SBarry Smith   PetscFunctionReturn(0);
2134b9ad928SBarry Smith }
2144b9ad928SBarry Smith 
2154b9ad928SBarry Smith #undef __FUNCT__
2164b9ad928SBarry Smith #define __FUNCT__ "PCDestroy_Redundant"
2176849ba73SBarry Smith static PetscErrorCode PCDestroy_Redundant(PC pc)
2184b9ad928SBarry Smith {
2194b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
220dfbe8321SBarry Smith   PetscErrorCode ierr;
2214b9ad928SBarry Smith 
2224b9ad928SBarry Smith   PetscFunctionBegin;
2234b9ad928SBarry Smith   if (red->scatterin)  {ierr = VecScatterDestroy(red->scatterin);CHKERRQ(ierr);}
2244b9ad928SBarry Smith   if (red->scatterout) {ierr = VecScatterDestroy(red->scatterout);CHKERRQ(ierr);}
2253f457be1SHong Zhang   if (red->ysub)       {ierr = VecDestroy(red->ysub);CHKERRQ(ierr);}
2263f457be1SHong Zhang   if (red->xsub)       {ierr = VecDestroy(red->xsub);CHKERRQ(ierr);}
2273f457be1SHong Zhang   if (red->xdup)       {ierr = VecDestroy(red->xdup);CHKERRQ(ierr);}
2283f457be1SHong Zhang   if (red->ydup)       {ierr = VecDestroy(red->ydup);CHKERRQ(ierr);}
229b3804887SHong Zhang   if (red->pmats) {
230b3804887SHong Zhang     ierr = MatDestroy(red->pmats);CHKERRQ(ierr);
2313f457be1SHong Zhang   }
232e5a9bf91SBarry Smith   if (red->psubcomm) {ierr = PetscSubcommDestroy(red->psubcomm);CHKERRQ(ierr);}
2333e065800SHong Zhang   if (red->ksp) {ierr = KSPDestroy(red->ksp);CHKERRQ(ierr);}
2344b9ad928SBarry Smith   ierr = PetscFree(red);CHKERRQ(ierr);
2354b9ad928SBarry Smith   PetscFunctionReturn(0);
2364b9ad928SBarry Smith }
2374b9ad928SBarry Smith 
2384b9ad928SBarry Smith #undef __FUNCT__
2394b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_Redundant"
2406849ba73SBarry Smith static PetscErrorCode PCSetFromOptions_Redundant(PC pc)
2414b9ad928SBarry Smith {
242a98ce0f4SHong Zhang   PetscErrorCode ierr;
243a98ce0f4SHong Zhang   PC_Redundant   *red = (PC_Redundant*)pc->data;
244a98ce0f4SHong Zhang 
2454b9ad928SBarry Smith   PetscFunctionBegin;
246a98ce0f4SHong Zhang   ierr = PetscOptionsHead("Redundant options");CHKERRQ(ierr);
24709a6bc64SHong Zhang   ierr = PetscOptionsInt("-pc_redundant_number","Number of redundant pc","PCRedundantSetNumber",red->nsubcomm,&red->nsubcomm,0);CHKERRQ(ierr);
248a98ce0f4SHong Zhang   ierr = PetscOptionsTail();CHKERRQ(ierr);
2494b9ad928SBarry Smith   PetscFunctionReturn(0);
2504b9ad928SBarry Smith }
2514b9ad928SBarry Smith 
2524b9ad928SBarry Smith EXTERN_C_BEGIN
2534b9ad928SBarry Smith #undef __FUNCT__
25409a6bc64SHong Zhang #define __FUNCT__ "PCRedundantSetNumber_Redundant"
25509a6bc64SHong Zhang PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetNumber_Redundant(PC pc,PetscInt nreds)
25609a6bc64SHong Zhang {
25709a6bc64SHong Zhang   PC_Redundant *red = (PC_Redundant*)pc->data;
25809a6bc64SHong Zhang 
25909a6bc64SHong Zhang   PetscFunctionBegin;
26009a6bc64SHong Zhang   red->nsubcomm = nreds;
26109a6bc64SHong Zhang   PetscFunctionReturn(0);
26209a6bc64SHong Zhang }
26309a6bc64SHong Zhang EXTERN_C_END
26409a6bc64SHong Zhang 
26509a6bc64SHong Zhang #undef __FUNCT__
26609a6bc64SHong Zhang #define __FUNCT__ "PCRedundantSetNumber"
26709a6bc64SHong Zhang /*@
26809a6bc64SHong Zhang    PCRedundantSetNumber - Sets the number of redundant preconditioner contexts.
26909a6bc64SHong Zhang 
270*3f9fe445SBarry Smith    Logically Collective on PC
27109a6bc64SHong Zhang 
27209a6bc64SHong Zhang    Input Parameters:
27309a6bc64SHong Zhang +  pc - the preconditioner context
2749b21d695SBarry Smith -  nredundant - number of redundant preconditioner contexts; for example if you are using 64 MPI processes and
2759b21d695SBarry Smith                               use an nredundant of 4 there will be 4 parallel solves each on 16 = 64/4 processes.
27609a6bc64SHong Zhang 
27709a6bc64SHong Zhang    Level: advanced
27809a6bc64SHong Zhang 
27909a6bc64SHong Zhang .keywords: PC, redundant solve
28009a6bc64SHong Zhang @*/
28109a6bc64SHong Zhang PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetNumber(PC pc,PetscInt nredundant)
28209a6bc64SHong Zhang {
28309a6bc64SHong Zhang   PetscErrorCode ierr,(*f)(PC,PetscInt);
28409a6bc64SHong Zhang 
28509a6bc64SHong Zhang   PetscFunctionBegin;
2860700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28765e19b50SBarry Smith   if (nredundant <= 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "num of redundant pc %D must be positive",nredundant);
28809a6bc64SHong Zhang   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantSetNumber_C",(void (**)(void))&f);CHKERRQ(ierr);
28909a6bc64SHong Zhang   if (f) {
29009a6bc64SHong Zhang     ierr = (*f)(pc,nredundant);CHKERRQ(ierr);
29109a6bc64SHong Zhang   }
29209a6bc64SHong Zhang   PetscFunctionReturn(0);
29309a6bc64SHong Zhang }
29409a6bc64SHong Zhang 
29509a6bc64SHong Zhang EXTERN_C_BEGIN
29609a6bc64SHong Zhang #undef __FUNCT__
2974b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter_Redundant"
298dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetScatter_Redundant(PC pc,VecScatter in,VecScatter out)
2994b9ad928SBarry Smith {
3004b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
301dfbe8321SBarry Smith   PetscErrorCode ierr;
3024b9ad928SBarry Smith 
3034b9ad928SBarry Smith   PetscFunctionBegin;
3044b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)in);CHKERRQ(ierr);
305c3122656SLisandro Dalcin   if (red->scatterin) { ierr = VecScatterDestroy(red->scatterin);CHKERRQ(ierr); }
306c3122656SLisandro Dalcin   red->scatterin  = in;
3074b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)out);CHKERRQ(ierr);
308c3122656SLisandro Dalcin   if (red->scatterout) { ierr = VecScatterDestroy(red->scatterout);CHKERRQ(ierr); }
309c3122656SLisandro Dalcin   red->scatterout = out;
3104b9ad928SBarry Smith   PetscFunctionReturn(0);
3114b9ad928SBarry Smith }
3124b9ad928SBarry Smith EXTERN_C_END
3134b9ad928SBarry Smith 
3144b9ad928SBarry Smith #undef __FUNCT__
3154b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter"
3164b9ad928SBarry Smith /*@
3174b9ad928SBarry Smith    PCRedundantSetScatter - Sets the scatter used to copy values into the
3184b9ad928SBarry Smith      redundant local solve and the scatter to move them back into the global
3194b9ad928SBarry Smith      vector.
3204b9ad928SBarry Smith 
321*3f9fe445SBarry Smith    Logically Collective on PC
3224b9ad928SBarry Smith 
3234b9ad928SBarry Smith    Input Parameters:
3244b9ad928SBarry Smith +  pc - the preconditioner context
3254b9ad928SBarry Smith .  in - the scatter to move the values in
3264b9ad928SBarry Smith -  out - the scatter to move them out
3274b9ad928SBarry Smith 
3284b9ad928SBarry Smith    Level: advanced
3294b9ad928SBarry Smith 
3304b9ad928SBarry Smith .keywords: PC, redundant solve
3314b9ad928SBarry Smith @*/
332dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetScatter(PC pc,VecScatter in,VecScatter out)
3334b9ad928SBarry Smith {
334dfbe8321SBarry Smith   PetscErrorCode ierr,(*f)(PC,VecScatter,VecScatter);
3354b9ad928SBarry Smith 
3364b9ad928SBarry Smith   PetscFunctionBegin;
3370700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3380700a824SBarry Smith   PetscValidHeaderSpecific(in,VEC_SCATTER_CLASSID,2);
3390700a824SBarry Smith   PetscValidHeaderSpecific(out,VEC_SCATTER_CLASSID,3);
3404b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantSetScatter_C",(void (**)(void))&f);CHKERRQ(ierr);
3414b9ad928SBarry Smith   if (f) {
3424b9ad928SBarry Smith     ierr = (*f)(pc,in,out);CHKERRQ(ierr);
3434b9ad928SBarry Smith   }
3444b9ad928SBarry Smith   PetscFunctionReturn(0);
3454b9ad928SBarry Smith }
3464b9ad928SBarry Smith 
3474b9ad928SBarry Smith EXTERN_C_BEGIN
3484b9ad928SBarry Smith #undef __FUNCT__
3494b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetPC_Redundant"
350dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetPC_Redundant(PC pc,PC *innerpc)
3514b9ad928SBarry Smith {
3525f06b7aaSBarry Smith   PetscErrorCode ierr;
3534b9ad928SBarry Smith   PC_Redundant   *red = (PC_Redundant*)pc->data;
3545f06b7aaSBarry Smith   MPI_Comm       comm,subcomm;
3555f06b7aaSBarry Smith   const char     *prefix;
3564b9ad928SBarry Smith 
3574b9ad928SBarry Smith   PetscFunctionBegin;
3585f06b7aaSBarry Smith   if (!red->psubcomm) {
3595f06b7aaSBarry Smith     ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
3605f06b7aaSBarry Smith     ierr = PetscSubcommCreate(comm,red->nsubcomm,&red->psubcomm);CHKERRQ(ierr);
3615f06b7aaSBarry Smith     ierr = PetscLogObjectMemory(pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
3625f06b7aaSBarry Smith 
3635f06b7aaSBarry Smith     /* create a new PC that processors in each subcomm have copy of */
3645f06b7aaSBarry Smith     subcomm = red->psubcomm->comm;
3655f06b7aaSBarry Smith     ierr = KSPCreate(subcomm,&red->ksp);CHKERRQ(ierr);
3665f06b7aaSBarry Smith     ierr = PetscObjectIncrementTabLevel((PetscObject)red->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3675f06b7aaSBarry Smith     ierr = PetscLogObjectParent(pc,red->ksp);CHKERRQ(ierr);
3685f06b7aaSBarry Smith     ierr = KSPSetType(red->ksp,KSPPREONLY);CHKERRQ(ierr);
3695f06b7aaSBarry Smith     ierr = KSPGetPC(red->ksp,&red->pc);CHKERRQ(ierr);
3705f06b7aaSBarry Smith     ierr = PCSetType(red->pc,PCLU);CHKERRQ(ierr);
3715f06b7aaSBarry Smith 
3725f06b7aaSBarry Smith     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3735f06b7aaSBarry Smith     ierr = KSPSetOptionsPrefix(red->ksp,prefix);CHKERRQ(ierr);
3745f06b7aaSBarry Smith     ierr = KSPAppendOptionsPrefix(red->ksp,"redundant_");CHKERRQ(ierr);
3755f06b7aaSBarry Smith   }
3765f06b7aaSBarry Smith 
3775f06b7aaSBarry Smith   ierr = KSPGetPC(red->ksp,innerpc);CHKERRQ(ierr);
3784b9ad928SBarry Smith   PetscFunctionReturn(0);
3794b9ad928SBarry Smith }
3804b9ad928SBarry Smith EXTERN_C_END
3814b9ad928SBarry Smith 
3824b9ad928SBarry Smith #undef __FUNCT__
3834b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetPC"
3844b9ad928SBarry Smith /*@
3854b9ad928SBarry Smith    PCRedundantGetPC - Gets the sequential PC created by the redundant PC.
3864b9ad928SBarry Smith 
3874b9ad928SBarry Smith    Not Collective
3884b9ad928SBarry Smith 
3894b9ad928SBarry Smith    Input Parameter:
3904b9ad928SBarry Smith .  pc - the preconditioner context
3914b9ad928SBarry Smith 
3924b9ad928SBarry Smith    Output Parameter:
3934b9ad928SBarry Smith .  innerpc - the sequential PC
3944b9ad928SBarry Smith 
3954b9ad928SBarry Smith    Level: advanced
3964b9ad928SBarry Smith 
3974b9ad928SBarry Smith .keywords: PC, redundant solve
3984b9ad928SBarry Smith @*/
399dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetPC(PC pc,PC *innerpc)
4004b9ad928SBarry Smith {
401dfbe8321SBarry Smith   PetscErrorCode ierr,(*f)(PC,PC*);
4024b9ad928SBarry Smith 
4034b9ad928SBarry Smith   PetscFunctionBegin;
4040700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4054482741eSBarry Smith   PetscValidPointer(innerpc,2);
4064b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetPC_C",(void (**)(void))&f);CHKERRQ(ierr);
4074b9ad928SBarry Smith   if (f) {
4084b9ad928SBarry Smith     ierr = (*f)(pc,innerpc);CHKERRQ(ierr);
4094b9ad928SBarry Smith   }
4104b9ad928SBarry Smith   PetscFunctionReturn(0);
4114b9ad928SBarry Smith }
4124b9ad928SBarry Smith 
4134b9ad928SBarry Smith EXTERN_C_BEGIN
4144b9ad928SBarry Smith #undef __FUNCT__
4154b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators_Redundant"
416dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetOperators_Redundant(PC pc,Mat *mat,Mat *pmat)
4174b9ad928SBarry Smith {
4184b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
4194b9ad928SBarry Smith 
4204b9ad928SBarry Smith   PetscFunctionBegin;
421b3804887SHong Zhang   if (mat)  *mat  = red->pmats;
422b3804887SHong Zhang   if (pmat) *pmat = red->pmats;
4234b9ad928SBarry Smith   PetscFunctionReturn(0);
4244b9ad928SBarry Smith }
4254b9ad928SBarry Smith EXTERN_C_END
4264b9ad928SBarry Smith 
4274b9ad928SBarry Smith #undef __FUNCT__
4284b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators"
4294b9ad928SBarry Smith /*@
4304b9ad928SBarry Smith    PCRedundantGetOperators - gets the sequential matrix and preconditioner matrix
4314b9ad928SBarry Smith 
4324b9ad928SBarry Smith    Not Collective
4334b9ad928SBarry Smith 
4344b9ad928SBarry Smith    Input Parameter:
4354b9ad928SBarry Smith .  pc - the preconditioner context
4364b9ad928SBarry Smith 
4374b9ad928SBarry Smith    Output Parameters:
4384b9ad928SBarry Smith +  mat - the matrix
4394b9ad928SBarry Smith -  pmat - the (possibly different) preconditioner matrix
4404b9ad928SBarry Smith 
4414b9ad928SBarry Smith    Level: advanced
4424b9ad928SBarry Smith 
4434b9ad928SBarry Smith .keywords: PC, redundant solve
4444b9ad928SBarry Smith @*/
445dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetOperators(PC pc,Mat *mat,Mat *pmat)
4464b9ad928SBarry Smith {
447dfbe8321SBarry Smith   PetscErrorCode ierr,(*f)(PC,Mat*,Mat*);
4484b9ad928SBarry Smith 
4494b9ad928SBarry Smith   PetscFunctionBegin;
4500700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4514482741eSBarry Smith   if (mat)  PetscValidPointer(mat,2);
4524482741eSBarry Smith   if (pmat) PetscValidPointer(pmat,3);
4534b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetOperators_C",(void (**)(void))&f);CHKERRQ(ierr);
4544b9ad928SBarry Smith   if (f) {
4554b9ad928SBarry Smith     ierr = (*f)(pc,mat,pmat);CHKERRQ(ierr);
4564b9ad928SBarry Smith   }
4574b9ad928SBarry Smith   PetscFunctionReturn(0);
4584b9ad928SBarry Smith }
4594b9ad928SBarry Smith 
4604b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
46137a17b4dSBarry Smith /*MC
462a98ce0f4SHong Zhang      PCREDUNDANT - Runs a preconditioner for the entire problem on subgroups of processors
46337a17b4dSBarry Smith 
46437a17b4dSBarry Smith      Options for the redundant preconditioners can be set with -redundant_pc_xxx
46537a17b4dSBarry Smith 
46609391456SBarry Smith   Options Database:
4679b21d695SBarry Smith .  -pc_redundant_number <n> - number of redundant solves, for example if you are using 64 MPI processes and
4689b21d695SBarry Smith                               use an n of 4 there will be 4 parallel solves each on 16 = 64/4 processes.
46909391456SBarry Smith 
47037a17b4dSBarry Smith    Level: intermediate
47137a17b4dSBarry Smith 
47237a17b4dSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCRedundantSetScatter(),
4739b21d695SBarry Smith            PCRedundantGetPC(), PCRedundantGetOperators(), PCRedundantSetNumber()
47437a17b4dSBarry Smith M*/
47537a17b4dSBarry Smith 
4764b9ad928SBarry Smith EXTERN_C_BEGIN
4774b9ad928SBarry Smith #undef __FUNCT__
4784b9ad928SBarry Smith #define __FUNCT__ "PCCreate_Redundant"
479dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Redundant(PC pc)
4804b9ad928SBarry Smith {
481dfbe8321SBarry Smith   PetscErrorCode ierr;
4824b9ad928SBarry Smith   PC_Redundant   *red;
48369db28dcSHong Zhang   PetscMPIInt    size;
4843f457be1SHong Zhang 
4854b9ad928SBarry Smith   PetscFunctionBegin;
48638f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_Redundant,&red);CHKERRQ(ierr);
4877adad957SLisandro Dalcin   ierr = MPI_Comm_size(((PetscObject)pc)->comm,&size);CHKERRQ(ierr);
48869db28dcSHong Zhang   red->nsubcomm       = size;
4894b9ad928SBarry Smith   red->useparallelmat = PETSC_TRUE;
4901fbd8f88SHong Zhang   pc->data            = (void*)red;
4914b9ad928SBarry Smith 
4924b9ad928SBarry Smith   pc->ops->apply           = PCApply_Redundant;
4934b9ad928SBarry Smith   pc->ops->applytranspose  = 0;
4944b9ad928SBarry Smith   pc->ops->setup           = PCSetUp_Redundant;
4954b9ad928SBarry Smith   pc->ops->destroy         = PCDestroy_Redundant;
4964b9ad928SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Redundant;
4974b9ad928SBarry Smith   pc->ops->view            = PCView_Redundant;
4984b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantSetScatter_C","PCRedundantSetScatter_Redundant",
4994b9ad928SBarry Smith                     PCRedundantSetScatter_Redundant);CHKERRQ(ierr);
50009a6bc64SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantSetNumber_C","PCRedundantSetNumber_Redundant",
50109a6bc64SHong Zhang                     PCRedundantSetNumber_Redundant);CHKERRQ(ierr);
5024b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetPC_C","PCRedundantGetPC_Redundant",
5034b9ad928SBarry Smith                     PCRedundantGetPC_Redundant);CHKERRQ(ierr);
5044b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetOperators_C","PCRedundantGetOperators_Redundant",
5054b9ad928SBarry Smith                     PCRedundantGetOperators_Redundant);CHKERRQ(ierr);
5064b9ad928SBarry Smith   PetscFunctionReturn(0);
5074b9ad928SBarry Smith }
5084b9ad928SBarry Smith EXTERN_C_END
509