1b1a0a8a3SJed Brown #define PETSCKSP_DLL 2b1a0a8a3SJed Brown 3b1a0a8a3SJed Brown /* 4f746d493SDmitry Karpeev This file defines an "generalized" additive Schwarz preconditioner for any Mat implementation. 544fe18e5SDmitry Karpeev In this version each processor may have any number of subdomains and a subdomain may live on multiple 6f746d493SDmitry Karpeev processors. 7b1a0a8a3SJed Brown 8f746d493SDmitry Karpeev N - total number of true subdomains on all processors 9f746d493SDmitry Karpeev n - actual number of subdomains on this processor 10f746d493SDmitry Karpeev nmax - maximum number of subdomains per processor 11b1a0a8a3SJed Brown */ 12b1a0a8a3SJed Brown #include "private/pcimpl.h" /*I "petscpc.h" I*/ 13b1a0a8a3SJed Brown 14b1a0a8a3SJed Brown typedef struct { 15f746d493SDmitry Karpeev PetscInt N,n,nmax; 16b1a0a8a3SJed Brown PetscInt overlap; /* overlap requested by user */ 17b1a0a8a3SJed Brown KSP *ksp; /* linear solvers for each block */ 18f746d493SDmitry Karpeev Vec gx,gy; /* Merged work vectors */ 19f746d493SDmitry Karpeev Vec *x,*y; /* Split work vectors; storage aliases pieces of storage of the above merged vectors. */ 20f746d493SDmitry Karpeev IS gis, gis_local; /* merged ISs */ 21f746d493SDmitry Karpeev VecScatter grestriction; /* merged restriction */ 22f746d493SDmitry Karpeev VecScatter gprolongation; /* merged prolongation */ 23b1a0a8a3SJed Brown IS *is; /* index set that defines each overlapping subdomain */ 24f746d493SDmitry Karpeev IS *is_local; /* index set that defines each local subdomain (same as subdomain with the overlap removed); may be NULL */ 25f746d493SDmitry Karpeev Mat *pmat; /* subdomain block matrices */ 26f746d493SDmitry Karpeev PCGASMType type; /* use reduced interpolation, restriction or both */ 27b1a0a8a3SJed Brown PetscBool type_set; /* if user set this value (so won't change it for symmetric problems) */ 28b1a0a8a3SJed Brown PetscBool same_local_solves; /* flag indicating whether all local solvers are same */ 29b1a0a8a3SJed Brown PetscBool sort_indices; /* flag to sort subdomain indices */ 30f746d493SDmitry Karpeev } PC_GASM; 31b1a0a8a3SJed Brown 32b1a0a8a3SJed Brown #undef __FUNCT__ 33f746d493SDmitry Karpeev #define __FUNCT__ "PCView_GASM" 34f746d493SDmitry Karpeev static PetscErrorCode PCView_GASM(PC pc,PetscViewer viewer) 35b1a0a8a3SJed Brown { 36f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 37b1a0a8a3SJed Brown PetscErrorCode ierr; 38b1a0a8a3SJed Brown PetscMPIInt rank; 39b1a0a8a3SJed Brown PetscInt i,bsz; 40b1a0a8a3SJed Brown PetscBool iascii,isstring; 41b1a0a8a3SJed Brown PetscViewer sviewer; 42b1a0a8a3SJed Brown 43b1a0a8a3SJed Brown 44b1a0a8a3SJed Brown PetscFunctionBegin; 45b1a0a8a3SJed Brown ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 46b1a0a8a3SJed Brown ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 47b1a0a8a3SJed Brown if (iascii) { 48b1a0a8a3SJed Brown char overlaps[256] = "user-defined overlap",blocks[256] = "total subdomain blocks not yet set"; 49b1a0a8a3SJed Brown if (osm->overlap >= 0) {ierr = PetscSNPrintf(overlaps,sizeof overlaps,"amount of overlap = %D",osm->overlap);CHKERRQ(ierr);} 5044fe18e5SDmitry Karpeev if (osm->nmax > 0) {ierr = PetscSNPrintf(blocks,sizeof blocks,"max number of subdomain blocks = %D",osm->nmax);CHKERRQ(ierr);} 51f746d493SDmitry Karpeev ierr = PetscViewerASCIISynchronizedPrintf(viewer," [%d] number of local blocks = %D\n",(int)rank,osm->n);CHKERRQ(ierr); 52f746d493SDmitry Karpeev ierr = PetscViewerASCIIPrintf(viewer," Generalized additive Schwarz: %s, %s\n",blocks,overlaps);CHKERRQ(ierr); 53f746d493SDmitry Karpeev ierr = PetscViewerASCIIPrintf(viewer," Generalized additive Schwarz: restriction/interpolation type - %s\n",PCGASMTypes[osm->type]);CHKERRQ(ierr); 54b1a0a8a3SJed Brown ierr = MPI_Comm_rank(((PetscObject)pc)->comm,&rank);CHKERRQ(ierr); 55b1a0a8a3SJed Brown if (osm->same_local_solves) { 56b1a0a8a3SJed Brown if (osm->ksp) { 57b1a0a8a3SJed Brown ierr = PetscViewerASCIIPrintf(viewer," Local solve is same for all blocks, in the following KSP and PC objects:\n");CHKERRQ(ierr); 58b1a0a8a3SJed Brown ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 59b1a0a8a3SJed Brown if (!rank) { 60b1a0a8a3SJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 61b1a0a8a3SJed Brown ierr = KSPView(osm->ksp[0],sviewer);CHKERRQ(ierr); 62b1a0a8a3SJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 63b1a0a8a3SJed Brown } 64b1a0a8a3SJed Brown ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 65b1a0a8a3SJed Brown } 66b1a0a8a3SJed Brown } else { 67b1a0a8a3SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 68b1a0a8a3SJed Brown ierr = PetscViewerASCIIPrintf(viewer," Local solve info for each block is in the following KSP and PC objects:\n");CHKERRQ(ierr); 69b1a0a8a3SJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 70b1a0a8a3SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 71f746d493SDmitry Karpeev for (i=0; i<osm->nmax; i++) { 72b1a0a8a3SJed Brown ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 73f746d493SDmitry Karpeev if (i < osm->n) { 74b1a0a8a3SJed Brown ierr = ISGetLocalSize(osm->is[i],&bsz);CHKERRQ(ierr); 75b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(sviewer,"[%d] local block number %D, size = %D\n",(int)rank,i,bsz);CHKERRQ(ierr); 76b1a0a8a3SJed Brown ierr = KSPView(osm->ksp[i],sviewer);CHKERRQ(ierr); 77b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(sviewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 78b1a0a8a3SJed Brown } 79b1a0a8a3SJed Brown ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 80b1a0a8a3SJed Brown } 81b1a0a8a3SJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 82b1a0a8a3SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 83b1a0a8a3SJed Brown } 84b1a0a8a3SJed Brown } else if (isstring) { 85f746d493SDmitry Karpeev ierr = PetscViewerStringSPrintf(viewer," blocks=%D, overlap=%D, type=%s",osm->n,osm->overlap,PCGASMTypes[osm->type]);CHKERRQ(ierr); 86b1a0a8a3SJed Brown ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 87b1a0a8a3SJed Brown if (osm->ksp) {ierr = KSPView(osm->ksp[0],sviewer);CHKERRQ(ierr);} 88b1a0a8a3SJed Brown ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 89b1a0a8a3SJed Brown } else { 90f746d493SDmitry Karpeev SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCGASM",((PetscObject)viewer)->type_name); 91b1a0a8a3SJed Brown } 92b1a0a8a3SJed Brown PetscFunctionReturn(0); 93b1a0a8a3SJed Brown } 94b1a0a8a3SJed Brown 95b1a0a8a3SJed Brown #undef __FUNCT__ 96f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMPrintSubdomains" 97f746d493SDmitry Karpeev static PetscErrorCode PCGASMPrintSubdomains(PC pc) 98b1a0a8a3SJed Brown { 99f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 100b1a0a8a3SJed Brown const char *prefix; 101b1a0a8a3SJed Brown char fname[PETSC_MAX_PATH_LEN+1]; 102b1a0a8a3SJed Brown PetscViewer viewer; 103b1a0a8a3SJed Brown PetscInt i,j,nidx; 104b1a0a8a3SJed Brown const PetscInt *idx; 105b1a0a8a3SJed Brown PetscErrorCode ierr; 106b1a0a8a3SJed Brown 107b1a0a8a3SJed Brown PetscFunctionBegin; 108b1a0a8a3SJed Brown ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 109f746d493SDmitry Karpeev ierr = PetscOptionsGetString(prefix,"-pc_gasm_print_subdomains",fname,PETSC_MAX_PATH_LEN,PETSC_NULL);CHKERRQ(ierr); 110b1a0a8a3SJed Brown if (fname[0] == 0) { ierr = PetscStrcpy(fname,"stdout");CHKERRQ(ierr); }; 111b1a0a8a3SJed Brown ierr = PetscViewerASCIIOpen(((PetscObject)pc)->comm,fname,&viewer);CHKERRQ(ierr); 112f746d493SDmitry Karpeev for (i=0;i<osm->n;++i) { 113b1a0a8a3SJed Brown ierr = ISGetLocalSize(osm->is[i],&nidx);CHKERRQ(ierr); 114b1a0a8a3SJed Brown ierr = ISGetIndices(osm->is[i],&idx);CHKERRQ(ierr); 115b1a0a8a3SJed Brown for (j=0; j<nidx; j++) { 116b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D ",idx[j]);CHKERRQ(ierr); 117b1a0a8a3SJed Brown } 118b1a0a8a3SJed Brown ierr = ISRestoreIndices(osm->is[i],&idx);CHKERRQ(ierr); 119b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); 120b1a0a8a3SJed Brown if (osm->is_local) { 121b1a0a8a3SJed Brown ierr = ISGetLocalSize(osm->is_local[i],&nidx);CHKERRQ(ierr); 122b1a0a8a3SJed Brown ierr = ISGetIndices(osm->is_local[i],&idx);CHKERRQ(ierr); 123b1a0a8a3SJed Brown for (j=0; j<nidx; j++) { 124b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D ",idx[j]);CHKERRQ(ierr); 125b1a0a8a3SJed Brown } 126b1a0a8a3SJed Brown ierr = ISRestoreIndices(osm->is_local[i],&idx);CHKERRQ(ierr); 127b1a0a8a3SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); 128b1a0a8a3SJed Brown } 129b1a0a8a3SJed Brown } 130b1a0a8a3SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 131b1a0a8a3SJed Brown ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr); 132b1a0a8a3SJed Brown PetscFunctionReturn(0); 133b1a0a8a3SJed Brown } 134b1a0a8a3SJed Brown 135b1a0a8a3SJed Brown #undef __FUNCT__ 136f746d493SDmitry Karpeev #define __FUNCT__ "PCSetUp_GASM" 137f746d493SDmitry Karpeev static PetscErrorCode PCSetUp_GASM(PC pc) 138b1a0a8a3SJed Brown { 139f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 140b1a0a8a3SJed Brown PetscErrorCode ierr; 141b1a0a8a3SJed Brown PetscBool symset,flg; 142f746d493SDmitry Karpeev PetscInt i,firstRow,lastRow; 143b1a0a8a3SJed Brown PetscMPIInt size; 144b1a0a8a3SJed Brown MatReuse scall = MAT_REUSE_MATRIX; 145b1a0a8a3SJed Brown KSP ksp; 146b1a0a8a3SJed Brown PC subpc; 147b1a0a8a3SJed Brown const char *prefix,*pprefix; 148f746d493SDmitry Karpeev PetscInt dn; /* Number of indices in a single subdomain assigned to this processor. */ 149f746d493SDmitry Karpeev const PetscInt *didx; /* Indices from a single subdomain assigned to this processor. */ 150f746d493SDmitry Karpeev PetscInt ddn; /* Number of indices in all subdomains assigned to this processor. */ 151f746d493SDmitry Karpeev PetscInt *ddidx; /* Indices of all subdomains assigned to this processor. */ 152f746d493SDmitry Karpeev IS gid; /* Identity IS of the size of all subdomains assigned to this processor. */ 153f746d493SDmitry Karpeev Vec x,y; 154f746d493SDmitry Karpeev PetscScalar *gxarray, *gyarray; 155f746d493SDmitry Karpeev IS *is; 156b1a0a8a3SJed Brown 157b1a0a8a3SJed Brown PetscFunctionBegin; 158b1a0a8a3SJed Brown if (!pc->setupcalled) { 159b1a0a8a3SJed Brown 160b1a0a8a3SJed Brown if (!osm->type_set) { 161b1a0a8a3SJed Brown ierr = MatIsSymmetricKnown(pc->pmat,&symset,&flg);CHKERRQ(ierr); 162f746d493SDmitry Karpeev if (symset && flg) { osm->type = PC_GASM_BASIC; } 163b1a0a8a3SJed Brown } 164b1a0a8a3SJed Brown 16544fe18e5SDmitry Karpeev if (osm->N == PETSC_DECIDE && osm->n < 1) { 166b1a0a8a3SJed Brown /* no subdomains given, use one per processor */ 16744fe18e5SDmitry Karpeev osm->nmax = osm->n = 1; 168b1a0a8a3SJed Brown ierr = MPI_Comm_size(((PetscObject)pc)->comm,&size);CHKERRQ(ierr); 169f746d493SDmitry Karpeev osm->N = size; 170f746d493SDmitry Karpeev } else if (osm->N == PETSC_DECIDE) { 171b1a0a8a3SJed Brown PetscInt inwork[2], outwork[2]; 172f746d493SDmitry Karpeev /* determine global number of subdomains and the max number of local subdomains */ 173f746d493SDmitry Karpeev inwork[0] = inwork[1] = osm->n; 174b1a0a8a3SJed Brown ierr = MPI_Allreduce(inwork,outwork,1,MPIU_2INT,PetscMaxSum_Op,((PetscObject)pc)->comm);CHKERRQ(ierr); 175f746d493SDmitry Karpeev osm->nmax = outwork[0]; 176f746d493SDmitry Karpeev osm->N = outwork[1]; 177b1a0a8a3SJed Brown } 178b1a0a8a3SJed Brown if (!osm->is){ /* create the index sets */ 179f746d493SDmitry Karpeev ierr = PCGASMCreateSubdomains(pc->pmat,osm->n,&osm->is);CHKERRQ(ierr); 180b1a0a8a3SJed Brown } 181*93c1ec32SDmitry Karpeev if (!osm->is_local) { 182*93c1ec32SDmitry Karpeev /* 183*93c1ec32SDmitry Karpeev This indicates that osm->is should define a nonoverlapping decomposition 184*93c1ec32SDmitry Karpeev (there is no way to really guarantee that if subdomains are set by the user through PCGASMSetLocalSubdomains, 185*93c1ec32SDmitry Karpeev but the assumption is that either the user does the right thing, or subdomains in ossm->is have been created 186*93c1ec32SDmitry Karpeev via PCGASMCreateSubdomains, which guarantees a nonoverlapping decomposition). 187*93c1ec32SDmitry Karpeev Therefore, osm->is will be used to define osm->is_local. 188*93c1ec32SDmitry Karpeev If a nonzero overlap has been requested by the user, then osm->is will be expanded and will overlap, 189*93c1ec32SDmitry Karpeev so osm->is_local should obtain a copy of osm->is while they are still (presumably) nonoverlapping. 190*93c1ec32SDmitry Karpeev Otherwise (no overlap has been requested), osm->is_local are simply aliases for osm->is. 191*93c1ec32SDmitry Karpeev */ 192f746d493SDmitry Karpeev ierr = PetscMalloc(osm->n*sizeof(IS),&osm->is_local);CHKERRQ(ierr); 193f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 194b1a0a8a3SJed Brown if (osm->overlap > 0) { /* With positive overlap, osm->is[i] will be modified */ 195b1a0a8a3SJed Brown ierr = ISDuplicate(osm->is[i],&osm->is_local[i]);CHKERRQ(ierr); 196b1a0a8a3SJed Brown ierr = ISCopy(osm->is[i],osm->is_local[i]);CHKERRQ(ierr); 197b1a0a8a3SJed Brown } else { 198b1a0a8a3SJed Brown ierr = PetscObjectReference((PetscObject)osm->is[i]);CHKERRQ(ierr); 199b1a0a8a3SJed Brown osm->is_local[i] = osm->is[i]; 200b1a0a8a3SJed Brown } 201b1a0a8a3SJed Brown } 202b1a0a8a3SJed Brown } 203*93c1ec32SDmitry Karpeev /* Beyond this point osm->is_local is not null. */ 204*93c1ec32SDmitry Karpeev if (osm->overlap > 0) { 205*93c1ec32SDmitry Karpeev /* Extend the "overlapping" regions by a number of steps */ 206*93c1ec32SDmitry Karpeev ierr = MatIncreaseOverlap(pc->pmat,osm->n,osm->is,osm->overlap);CHKERRQ(ierr); 207*93c1ec32SDmitry Karpeev } 208b1a0a8a3SJed Brown ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 209b1a0a8a3SJed Brown flg = PETSC_FALSE; 210f746d493SDmitry Karpeev ierr = PetscOptionsGetBool(prefix,"-pc_gasm_print_subdomains",&flg,PETSC_NULL);CHKERRQ(ierr); 211f746d493SDmitry Karpeev if (flg) { ierr = PCGASMPrintSubdomains(pc);CHKERRQ(ierr); } 212b1a0a8a3SJed Brown 213b1a0a8a3SJed Brown if (osm->sort_indices) { 214f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 215b1a0a8a3SJed Brown ierr = ISSort(osm->is[i]);CHKERRQ(ierr); 216b1a0a8a3SJed Brown ierr = ISSort(osm->is_local[i]);CHKERRQ(ierr); 217b1a0a8a3SJed Brown } 218b1a0a8a3SJed Brown } 219f746d493SDmitry Karpeev /* Merge the ISs, create merged vectors and scatter contexts. */ 220*93c1ec32SDmitry Karpeev /* Restriction ISs. */ 221f746d493SDmitry Karpeev ddn = 0; 222f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 223f746d493SDmitry Karpeev ierr = ISGetLocalSize(osm->is[i],&dn); CHKERRQ(ierr); 224f746d493SDmitry Karpeev ddn += dn; 225f746d493SDmitry Karpeev } 226f746d493SDmitry Karpeev ierr = PetscMalloc(ddn*sizeof(PetscInt), &ddidx); CHKERRQ(ierr); 227f746d493SDmitry Karpeev ddn = 0; 228f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 229f746d493SDmitry Karpeev ierr = ISGetLocalSize(osm->is[i],&dn); CHKERRQ(ierr); 230f746d493SDmitry Karpeev ierr = ISGetIndices(osm->is[i],&didx); CHKERRQ(ierr); 231f746d493SDmitry Karpeev ierr = PetscMemcpy(ddidx+ddn, didx, sizeof(PetscInt)*dn); CHKERRQ(ierr); 232f746d493SDmitry Karpeev ierr = ISRestoreIndices(osm->is[i], &didx); CHKERRQ(ierr); 233*93c1ec32SDmitry Karpeev ddn += dn; 234f746d493SDmitry Karpeev } 235f746d493SDmitry Karpeev ierr = ISCreateGeneral(((PetscObject)(pc))->comm, ddn, ddidx, PETSC_OWN_POINTER, &osm->gis); CHKERRQ(ierr); 236f746d493SDmitry Karpeev ierr = MatGetVecs(pc->pmat,&x,&y);CHKERRQ(ierr); 237f746d493SDmitry Karpeev ierr = VecCreateMPI(((PetscObject)pc)->comm, ddn, PETSC_DECIDE, &osm->gx); CHKERRQ(ierr); 238f746d493SDmitry Karpeev ierr = VecDuplicate(osm->gx,&osm->gy); CHKERRQ(ierr); 239f746d493SDmitry Karpeev ierr = ISCreateStride(((PetscObject)pc)->comm,ddn,0,1, &gid); CHKERRQ(ierr); 240f746d493SDmitry Karpeev ierr = VecScatterCreate(x,osm->gis,osm->gx,gid, &(osm->grestriction)); CHKERRQ(ierr); 241f746d493SDmitry Karpeev ierr = ISDestroy(gid); CHKERRQ(ierr); 242*93c1ec32SDmitry Karpeev /* Prolongation ISs */ 243*93c1ec32SDmitry Karpeev { PetscInt dn_local; /* Number of indices in the local part of single domain assigned to this processor. */ 244f746d493SDmitry Karpeev const PetscInt *didx_local; /* Global indices from the local part of a single domain assigned to this processor. */ 245f746d493SDmitry Karpeev PetscInt ddn_local; /* Number of indices in the local part of the disjoint union all domains assigned to this processor. */ 246f746d493SDmitry Karpeev PetscInt *ddidx_local; /* Global indices of the local part of the disjoint union of all domains assigned to this processor. */ 247f746d493SDmitry Karpeev /**/ 248*93c1ec32SDmitry Karpeev ISLocalToGlobalMapping ltog; /* Map from global to local indices on the disjoint union of subdomains: "local" ind's run from 0 to ddn-1. */ 249*93c1ec32SDmitry Karpeev PetscInt *ddidx_llocal; /* Mapped local indices of the disjoint union of local parts of subdomains. */ 250f746d493SDmitry Karpeev PetscInt ddn_llocal; /* Number of indices in ddidx_llocal; must equal ddn_local, or else gis_local is not a sub-IS of gis. */ 251f746d493SDmitry Karpeev IS gis_llocal; /* IS with ddidx_llocal indices. */ 252f746d493SDmitry Karpeev PetscInt j; 253f746d493SDmitry Karpeev ddn_local = 0; 254f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 255f746d493SDmitry Karpeev ierr = ISGetLocalSize(osm->is_local[i],&dn_local); CHKERRQ(ierr); 256f746d493SDmitry Karpeev ddn_local += dn_local; 257f746d493SDmitry Karpeev } 258f746d493SDmitry Karpeev ierr = PetscMalloc(ddn_local*sizeof(PetscInt), &ddidx_local); CHKERRQ(ierr); 259f746d493SDmitry Karpeev ddn_local = 0; 260f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 261f746d493SDmitry Karpeev ierr = ISGetLocalSize(osm->is_local[i],&dn_local); CHKERRQ(ierr); 262f746d493SDmitry Karpeev ierr = ISGetIndices(osm->is_local[i],&didx_local); CHKERRQ(ierr); 263f746d493SDmitry Karpeev ierr = PetscMemcpy(ddidx_local+ddn_local, didx_local, sizeof(PetscInt)*dn_local); CHKERRQ(ierr); 264f746d493SDmitry Karpeev ierr = ISRestoreIndices(osm->is_local[i], &didx_local); CHKERRQ(ierr); 265f746d493SDmitry Karpeev ddn_local += dn_local; 266f746d493SDmitry Karpeev } 267ab3e923fSDmitry Karpeev ierr = PetscMalloc(sizeof(PetscInt)*ddn_local, &ddidx_llocal); CHKERRQ(ierr); 268f746d493SDmitry Karpeev ierr = ISCreateGeneral(((PetscObject)pc)->comm, ddn_local, ddidx_local, PETSC_OWN_POINTER, &(osm->gis_local)); CHKERRQ(ierr); 269f746d493SDmitry Karpeev ierr = ISLocalToGlobalMappingCreateIS(osm->gis,<og);CHKERRQ(ierr); 270f746d493SDmitry Karpeev ierr = ISGlobalToLocalMappingApply(ltog,IS_GTOLM_DROP,dn_local,ddidx_local,&ddn_llocal,ddidx_llocal);CHKERRQ(ierr); 271b1a0a8a3SJed Brown ierr = ISLocalToGlobalMappingDestroy(ltog);CHKERRQ(ierr); 272*93c1ec32SDmitry Karpeev if (ddn_llocal != ddn_local) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"gis_local contains %D indices outside of gis", ddn_llocal - ddn_local); 273f746d493SDmitry Karpeev /* Now convert these localized indices into the global indices into the merged output vector. */ 274f746d493SDmitry Karpeev ierr = VecGetOwnershipRange(osm->gy, &firstRow, &lastRow); CHKERRQ(ierr); 275f746d493SDmitry Karpeev for(j=0; j < ddn_llocal; ++j) { 276f746d493SDmitry Karpeev ddidx_llocal[j] += firstRow; 277f746d493SDmitry Karpeev } 278f746d493SDmitry Karpeev ierr = ISCreateGeneral(PETSC_COMM_SELF,ddn_llocal,ddidx_llocal,PETSC_OWN_POINTER,&gis_llocal); CHKERRQ(ierr); 279f746d493SDmitry Karpeev ierr = VecScatterCreate(y,osm->gis_local,osm->gy,gis_llocal,&osm->gprolongation); CHKERRQ(ierr); 280f746d493SDmitry Karpeev ierr = ISDestroy(gis_llocal);CHKERRQ(ierr); 281b1a0a8a3SJed Brown } 282f746d493SDmitry Karpeev /* Create the subdomain work vectors. */ 283f746d493SDmitry Karpeev ierr = PetscMalloc(osm->n*sizeof(Vec),&osm->x);CHKERRQ(ierr); 284f746d493SDmitry Karpeev ierr = PetscMalloc(osm->n*sizeof(Vec),&osm->y);CHKERRQ(ierr); 285f746d493SDmitry Karpeev ierr = VecGetOwnershipRange(osm->gx, &firstRow, &lastRow);CHKERRQ(ierr); 286f746d493SDmitry Karpeev ierr = VecGetArray(osm->gx, &gxarray); CHKERRQ(ierr); 287f746d493SDmitry Karpeev ierr = VecGetArray(osm->gy, &gyarray); CHKERRQ(ierr); 288f746d493SDmitry Karpeev for (i=0, ddn=0; i<osm->n; ++i, ddn += dn) { 289f746d493SDmitry Karpeev ierr = ISGetLocalSize(osm->is[i],&dn);CHKERRQ(ierr); 290f746d493SDmitry Karpeev ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dn,gxarray+ddn,&osm->x[i]);CHKERRQ(ierr); 291f746d493SDmitry Karpeev ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dn,gyarray+ddn,&osm->y[i]);CHKERRQ(ierr); 292b1a0a8a3SJed Brown } 293f746d493SDmitry Karpeev ierr = VecRestoreArray(osm->gx, &gxarray); CHKERRQ(ierr); 294f746d493SDmitry Karpeev ierr = VecRestoreArray(osm->gy, &gyarray); CHKERRQ(ierr); 295f746d493SDmitry Karpeev ierr = VecDestroy(x); CHKERRQ(ierr); 296f746d493SDmitry Karpeev ierr = VecDestroy(y); CHKERRQ(ierr); 297b1a0a8a3SJed Brown /* Create the local solvers */ 298f746d493SDmitry Karpeev ierr = PetscMalloc(osm->n*sizeof(KSP *),&osm->ksp);CHKERRQ(ierr); 29944fe18e5SDmitry Karpeev for (i=0; i<osm->n; i++) { /* KSPs are local */ 300b1a0a8a3SJed Brown ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 301b1a0a8a3SJed Brown ierr = PetscLogObjectParent(pc,ksp);CHKERRQ(ierr); 302b1a0a8a3SJed Brown ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr); 303b1a0a8a3SJed Brown ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 304b1a0a8a3SJed Brown ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr); 305b1a0a8a3SJed Brown ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 306b1a0a8a3SJed Brown ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 307b1a0a8a3SJed Brown ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 308b1a0a8a3SJed Brown osm->ksp[i] = ksp; 309b1a0a8a3SJed Brown } 310b1a0a8a3SJed Brown scall = MAT_INITIAL_MATRIX; 311b1a0a8a3SJed Brown 312b1a0a8a3SJed Brown } else { 313b1a0a8a3SJed Brown /* 314b1a0a8a3SJed Brown Destroy the blocks from the previous iteration 315b1a0a8a3SJed Brown */ 316b1a0a8a3SJed Brown if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 317f746d493SDmitry Karpeev ierr = MatDestroyMatrices(osm->n,&osm->pmat);CHKERRQ(ierr); 318b1a0a8a3SJed Brown scall = MAT_INITIAL_MATRIX; 319b1a0a8a3SJed Brown } 320b1a0a8a3SJed Brown } 321b1a0a8a3SJed Brown 322b1a0a8a3SJed Brown /* 323f746d493SDmitry Karpeev Extract out the submatrices. 324b1a0a8a3SJed Brown */ 325f746d493SDmitry Karpeev ierr = PetscMalloc(sizeof(IS)*osm->nmax, &is); CHKERRQ(ierr); 326f746d493SDmitry Karpeev for(i=0; i<osm->n; ++i) { 327f746d493SDmitry Karpeev is[i] = osm->is[i]; 328f746d493SDmitry Karpeev } 329f746d493SDmitry Karpeev for (i=osm->n; i<osm->nmax; i++) { 330f746d493SDmitry Karpeev ierr = ISCreateStride(((PetscObject)pc)->comm,0,0,1,&is[i]);CHKERRQ(ierr); 331f746d493SDmitry Karpeev } 33244fe18e5SDmitry Karpeev ierr = MatGetSubMatrices(pc->pmat,osm->n,osm->is,is,scall,&osm->pmat);CHKERRQ(ierr); 333b1a0a8a3SJed Brown if (scall == MAT_INITIAL_MATRIX) { 334b1a0a8a3SJed Brown ierr = PetscObjectGetOptionsPrefix((PetscObject)pc->pmat,&pprefix);CHKERRQ(ierr); 335f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 336b1a0a8a3SJed Brown ierr = PetscLogObjectParent(pc,osm->pmat[i]);CHKERRQ(ierr); 337b1a0a8a3SJed Brown ierr = PetscObjectSetOptionsPrefix((PetscObject)osm->pmat[i],pprefix);CHKERRQ(ierr); 338b1a0a8a3SJed Brown } 339b1a0a8a3SJed Brown } 340b1a0a8a3SJed Brown 341b1a0a8a3SJed Brown /* Return control to the user so that the submatrices can be modified (e.g., to apply 342b1a0a8a3SJed Brown different boundary conditions for the submatrices than for the global problem) */ 34344fe18e5SDmitry Karpeev ierr = PCModifySubMatrices(pc,osm->n,is,is,osm->pmat,pc->modifysubmatricesP);CHKERRQ(ierr); 344f746d493SDmitry Karpeev for (i=osm->n; i<osm->nmax; i++) { 345f746d493SDmitry Karpeev ierr = ISDestroy(is[i]);CHKERRQ(ierr); 346f746d493SDmitry Karpeev } 347f746d493SDmitry Karpeev ierr = PetscFree(is); CHKERRQ(ierr); 348b1a0a8a3SJed Brown 349b1a0a8a3SJed Brown /* 350f746d493SDmitry Karpeev Loop over submatrices putting them into local ksp 351b1a0a8a3SJed Brown */ 352f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 353b1a0a8a3SJed Brown ierr = KSPSetOperators(osm->ksp[i],osm->pmat[i],osm->pmat[i],pc->flag);CHKERRQ(ierr); 354b1a0a8a3SJed Brown if (!pc->setupcalled) { 355b1a0a8a3SJed Brown ierr = KSPSetFromOptions(osm->ksp[i]);CHKERRQ(ierr); 356b1a0a8a3SJed Brown } 357b1a0a8a3SJed Brown } 358b1a0a8a3SJed Brown 359b1a0a8a3SJed Brown PetscFunctionReturn(0); 360b1a0a8a3SJed Brown } 361b1a0a8a3SJed Brown 362b1a0a8a3SJed Brown #undef __FUNCT__ 363f746d493SDmitry Karpeev #define __FUNCT__ "PCSetUpOnBlocks_GASM" 364f746d493SDmitry Karpeev static PetscErrorCode PCSetUpOnBlocks_GASM(PC pc) 365b1a0a8a3SJed Brown { 366f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 367b1a0a8a3SJed Brown PetscErrorCode ierr; 368b1a0a8a3SJed Brown PetscInt i; 369b1a0a8a3SJed Brown 370b1a0a8a3SJed Brown PetscFunctionBegin; 371f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 372b1a0a8a3SJed Brown ierr = KSPSetUp(osm->ksp[i]);CHKERRQ(ierr); 373b1a0a8a3SJed Brown } 374b1a0a8a3SJed Brown PetscFunctionReturn(0); 375b1a0a8a3SJed Brown } 376b1a0a8a3SJed Brown 377b1a0a8a3SJed Brown #undef __FUNCT__ 378f746d493SDmitry Karpeev #define __FUNCT__ "PCApply_GASM" 379f746d493SDmitry Karpeev static PetscErrorCode PCApply_GASM(PC pc,Vec x,Vec y) 380b1a0a8a3SJed Brown { 381f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 382b1a0a8a3SJed Brown PetscErrorCode ierr; 383f746d493SDmitry Karpeev PetscInt i; 384b1a0a8a3SJed Brown ScatterMode forward = SCATTER_FORWARD,reverse = SCATTER_REVERSE; 385b1a0a8a3SJed Brown 386b1a0a8a3SJed Brown PetscFunctionBegin; 387b1a0a8a3SJed Brown /* 388b1a0a8a3SJed Brown Support for limiting the restriction or interpolation to only local 389b1a0a8a3SJed Brown subdomain values (leaving the other values 0). 390b1a0a8a3SJed Brown */ 391f746d493SDmitry Karpeev if (!(osm->type & PC_GASM_RESTRICT)) { 392b1a0a8a3SJed Brown forward = SCATTER_FORWARD_LOCAL; 393b1a0a8a3SJed Brown /* have to zero the work RHS since scatter may leave some slots empty */ 394f746d493SDmitry Karpeev ierr = VecZeroEntries(osm->gx); CHKERRQ(ierr); 395b1a0a8a3SJed Brown } 396f746d493SDmitry Karpeev if (!(osm->type & PC_GASM_INTERPOLATE)) { 397b1a0a8a3SJed Brown reverse = SCATTER_REVERSE_LOCAL; 398b1a0a8a3SJed Brown } 399b1a0a8a3SJed Brown 400f746d493SDmitry Karpeev ierr = VecScatterBegin(osm->grestriction,x,osm->gx,INSERT_VALUES,forward);CHKERRQ(ierr); 401b1a0a8a3SJed Brown ierr = VecZeroEntries(y);CHKERRQ(ierr); 402f746d493SDmitry Karpeev ierr = VecScatterEnd(osm->grestriction,x,osm->gx,INSERT_VALUES,forward);CHKERRQ(ierr); 403b1a0a8a3SJed Brown /* do the local solves */ 404f746d493SDmitry Karpeev for (i=0; i<osm->n; ++i) { /* Note that the solves are local, so we can go to osm->n, rather than osm->nmax. */ 405b1a0a8a3SJed Brown ierr = KSPSolve(osm->ksp[i],osm->x[i],osm->y[i]);CHKERRQ(ierr); 406b1a0a8a3SJed Brown } 407f746d493SDmitry Karpeev ierr = VecScatterBegin(osm->gprolongation,osm->gy,y,ADD_VALUES,reverse);CHKERRQ(ierr); 408f746d493SDmitry Karpeev ierr = VecScatterEnd(osm->gprolongation,osm->gy,y,ADD_VALUES,reverse);CHKERRQ(ierr); 409b1a0a8a3SJed Brown PetscFunctionReturn(0); 410b1a0a8a3SJed Brown } 411b1a0a8a3SJed Brown 412b1a0a8a3SJed Brown #undef __FUNCT__ 413f746d493SDmitry Karpeev #define __FUNCT__ "PCApplyTranspose_GASM" 414f746d493SDmitry Karpeev static PetscErrorCode PCApplyTranspose_GASM(PC pc,Vec x,Vec y) 415b1a0a8a3SJed Brown { 416f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 417b1a0a8a3SJed Brown PetscErrorCode ierr; 418f746d493SDmitry Karpeev PetscInt i; 419b1a0a8a3SJed Brown ScatterMode forward = SCATTER_FORWARD,reverse = SCATTER_REVERSE; 420b1a0a8a3SJed Brown 421b1a0a8a3SJed Brown PetscFunctionBegin; 422b1a0a8a3SJed Brown /* 423b1a0a8a3SJed Brown Support for limiting the restriction or interpolation to only local 424b1a0a8a3SJed Brown subdomain values (leaving the other values 0). 425b1a0a8a3SJed Brown 426f746d493SDmitry Karpeev Note: these are reversed from the PCApply_GASM() because we are applying the 427b1a0a8a3SJed Brown transpose of the three terms 428b1a0a8a3SJed Brown */ 429f746d493SDmitry Karpeev if (!(osm->type & PC_GASM_INTERPOLATE)) { 430b1a0a8a3SJed Brown forward = SCATTER_FORWARD_LOCAL; 431b1a0a8a3SJed Brown /* have to zero the work RHS since scatter may leave some slots empty */ 432f746d493SDmitry Karpeev ierr = VecZeroEntries(osm->gx);CHKERRQ(ierr); 433b1a0a8a3SJed Brown } 434f746d493SDmitry Karpeev if (!(osm->type & PC_GASM_RESTRICT)) { 435b1a0a8a3SJed Brown reverse = SCATTER_REVERSE_LOCAL; 436b1a0a8a3SJed Brown } 437b1a0a8a3SJed Brown 438ab3e923fSDmitry Karpeev ierr = VecScatterBegin(osm->grestriction,x,osm->gx,INSERT_VALUES,forward);CHKERRQ(ierr); 439b1a0a8a3SJed Brown ierr = VecZeroEntries(y);CHKERRQ(ierr); 440ab3e923fSDmitry Karpeev ierr = VecScatterEnd(osm->grestriction,x,osm->gx,INSERT_VALUES,forward);CHKERRQ(ierr); 441b1a0a8a3SJed Brown /* do the local solves */ 442ab3e923fSDmitry Karpeev for (i=0; i<osm->n; ++i) { /* Note that the solves are local, so we can go to osm->n, rather than osm->nmax. */ 443b1a0a8a3SJed Brown ierr = KSPSolveTranspose(osm->ksp[i],osm->x[i],osm->y[i]);CHKERRQ(ierr); 444b1a0a8a3SJed Brown } 445ab3e923fSDmitry Karpeev ierr = VecScatterBegin(osm->gprolongation,osm->gy,y,ADD_VALUES,reverse);CHKERRQ(ierr); 446ab3e923fSDmitry Karpeev ierr = VecScatterEnd(osm->gprolongation,osm->gy,y,ADD_VALUES,reverse);CHKERRQ(ierr); 447b1a0a8a3SJed Brown PetscFunctionReturn(0); 448b1a0a8a3SJed Brown } 449b1a0a8a3SJed Brown 450b1a0a8a3SJed Brown #undef __FUNCT__ 451f746d493SDmitry Karpeev #define __FUNCT__ "PCDestroy_GASM" 452f746d493SDmitry Karpeev static PetscErrorCode PCDestroy_GASM(PC pc) 453b1a0a8a3SJed Brown { 454f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 455b1a0a8a3SJed Brown PetscErrorCode ierr; 456b1a0a8a3SJed Brown PetscInt i; 457b1a0a8a3SJed Brown 458b1a0a8a3SJed Brown PetscFunctionBegin; 459b1a0a8a3SJed Brown if (osm->ksp) { 460f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 461b1a0a8a3SJed Brown ierr = KSPDestroy(osm->ksp[i]);CHKERRQ(ierr); 462b1a0a8a3SJed Brown } 463b1a0a8a3SJed Brown ierr = PetscFree(osm->ksp);CHKERRQ(ierr); 464b1a0a8a3SJed Brown } 465b1a0a8a3SJed Brown if (osm->pmat) { 466f746d493SDmitry Karpeev if (osm->n > 0) { 467ab3e923fSDmitry Karpeev ierr = MatDestroyMatrices(osm->n,&osm->pmat);CHKERRQ(ierr); 468b1a0a8a3SJed Brown } 469b1a0a8a3SJed Brown } 470f746d493SDmitry Karpeev for (i=0; i<osm->n; i++) { 471b1a0a8a3SJed Brown ierr = VecDestroy(osm->x[i]);CHKERRQ(ierr); 472b1a0a8a3SJed Brown ierr = VecDestroy(osm->y[i]);CHKERRQ(ierr); 473b1a0a8a3SJed Brown } 474b1a0a8a3SJed Brown ierr = PetscFree(osm->x);CHKERRQ(ierr); 475b1a0a8a3SJed Brown ierr = PetscFree(osm->y);CHKERRQ(ierr); 476f746d493SDmitry Karpeev ierr = VecDestroy(osm->gx); CHKERRQ(ierr); 477ab3e923fSDmitry Karpeev ierr = VecDestroy(osm->gy); CHKERRQ(ierr); 478ab3e923fSDmitry Karpeev 479ab3e923fSDmitry Karpeev ierr = VecScatterDestroy(osm->grestriction); CHKERRQ(ierr); 480ab3e923fSDmitry Karpeev ierr = VecScatterDestroy(osm->gprolongation); CHKERRQ(ierr); 481f746d493SDmitry Karpeev 482b1a0a8a3SJed Brown if (osm->is) { 483ab3e923fSDmitry Karpeev ierr = PCGASMDestroySubdomains(osm->n,osm->is,osm->is_local);CHKERRQ(ierr); 484b1a0a8a3SJed Brown } 485b1a0a8a3SJed Brown ierr = PetscFree(osm);CHKERRQ(ierr); 486b1a0a8a3SJed Brown PetscFunctionReturn(0); 487b1a0a8a3SJed Brown } 488b1a0a8a3SJed Brown 489b1a0a8a3SJed Brown #undef __FUNCT__ 490f746d493SDmitry Karpeev #define __FUNCT__ "PCSetFromOptions_GASM" 491ab3e923fSDmitry Karpeev static PetscErrorCode PCSetFromOptions_GASM(PC pc) { 492f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 493b1a0a8a3SJed Brown PetscErrorCode ierr; 494b1a0a8a3SJed Brown PetscInt blocks,ovl; 495b1a0a8a3SJed Brown PetscBool symset,flg; 496f746d493SDmitry Karpeev PCGASMType gasmtype; 497b1a0a8a3SJed Brown 498b1a0a8a3SJed Brown PetscFunctionBegin; 499b1a0a8a3SJed Brown /* set the type to symmetric if matrix is symmetric */ 500b1a0a8a3SJed Brown if (!osm->type_set && pc->pmat) { 501b1a0a8a3SJed Brown ierr = MatIsSymmetricKnown(pc->pmat,&symset,&flg);CHKERRQ(ierr); 502f746d493SDmitry Karpeev if (symset && flg) { osm->type = PC_GASM_BASIC; } 503b1a0a8a3SJed Brown } 50444fe18e5SDmitry Karpeev ierr = PetscOptionsHead("Generalized additive Schwarz options");CHKERRQ(ierr); 505f746d493SDmitry Karpeev ierr = PetscOptionsInt("-pc_gasm_blocks","Number of subdomains","PCGASMSetTotalSubdomains",osm->n,&blocks,&flg);CHKERRQ(ierr); 506ab3e923fSDmitry Karpeev if (flg) {ierr = PCGASMSetTotalSubdomains(pc,blocks);CHKERRQ(ierr); } 507f746d493SDmitry Karpeev ierr = PetscOptionsInt("-pc_gasm_overlap","Number of grid points overlap","PCGASMSetOverlap",osm->overlap,&ovl,&flg);CHKERRQ(ierr); 508f746d493SDmitry Karpeev if (flg) {ierr = PCGASMSetOverlap(pc,ovl);CHKERRQ(ierr); } 509b1a0a8a3SJed Brown flg = PETSC_FALSE; 510f746d493SDmitry Karpeev ierr = PetscOptionsEnum("-pc_gasm_type","Type of restriction/extension","PCGASMSetType",PCGASMTypes,(PetscEnum)osm->type,(PetscEnum*)&gasmtype,&flg);CHKERRQ(ierr); 511f746d493SDmitry Karpeev if (flg) {ierr = PCGASMSetType(pc,gasmtype);CHKERRQ(ierr); } 512b1a0a8a3SJed Brown ierr = PetscOptionsTail();CHKERRQ(ierr); 513b1a0a8a3SJed Brown PetscFunctionReturn(0); 514b1a0a8a3SJed Brown } 515b1a0a8a3SJed Brown 516b1a0a8a3SJed Brown /*------------------------------------------------------------------------------------*/ 517b1a0a8a3SJed Brown 518b1a0a8a3SJed Brown EXTERN_C_BEGIN 519b1a0a8a3SJed Brown #undef __FUNCT__ 520f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetLocalSubdomains_GASM" 521f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetLocalSubdomains_GASM(PC pc,PetscInt n,IS is[],IS is_local[]) 522b1a0a8a3SJed Brown { 523f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 524b1a0a8a3SJed Brown PetscErrorCode ierr; 525b1a0a8a3SJed Brown PetscInt i; 526b1a0a8a3SJed Brown 527b1a0a8a3SJed Brown PetscFunctionBegin; 528b1a0a8a3SJed Brown if (n < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Each process must have 1 or more blocks, n = %D",n); 529f746d493SDmitry Karpeev if (pc->setupcalled && (n != osm->n || is)) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"PCGASMSetLocalSubdomains() should be called before calling PCSetUp()."); 530b1a0a8a3SJed Brown 531b1a0a8a3SJed Brown if (!pc->setupcalled) { 532*93c1ec32SDmitry Karpeev osm->n = n; 533*93c1ec32SDmitry Karpeev osm->is = 0; 534*93c1ec32SDmitry Karpeev osm->is_local = 0; 535b1a0a8a3SJed Brown if (is) { 536b1a0a8a3SJed Brown for (i=0; i<n; i++) {ierr = PetscObjectReference((PetscObject)is[i]);CHKERRQ(ierr);} 537b1a0a8a3SJed Brown } 538b1a0a8a3SJed Brown if (is_local) { 539b1a0a8a3SJed Brown for (i=0; i<n; i++) {ierr = PetscObjectReference((PetscObject)is_local[i]);CHKERRQ(ierr);} 540b1a0a8a3SJed Brown } 541b1a0a8a3SJed Brown if (osm->is) { 542ab3e923fSDmitry Karpeev ierr = PCGASMDestroySubdomains(osm->n,osm->is,osm->is_local);CHKERRQ(ierr); 543b1a0a8a3SJed Brown } 544b1a0a8a3SJed Brown if (is) { 545b1a0a8a3SJed Brown ierr = PetscMalloc(n*sizeof(IS),&osm->is);CHKERRQ(ierr); 546b1a0a8a3SJed Brown for (i=0; i<n; i++) { osm->is[i] = is[i]; } 547f746d493SDmitry Karpeev /* Flag indicating that the user has set overlapping subdomains so PCGASM should not increase their size. */ 548b1a0a8a3SJed Brown osm->overlap = -1; 549b1a0a8a3SJed Brown } 550b1a0a8a3SJed Brown if (is_local) { 551b1a0a8a3SJed Brown ierr = PetscMalloc(n*sizeof(IS),&osm->is_local);CHKERRQ(ierr); 552b1a0a8a3SJed Brown for (i=0; i<n; i++) { osm->is_local[i] = is_local[i]; } 553b1a0a8a3SJed Brown } 554b1a0a8a3SJed Brown } 555b1a0a8a3SJed Brown PetscFunctionReturn(0); 556b1a0a8a3SJed Brown } 557b1a0a8a3SJed Brown EXTERN_C_END 558b1a0a8a3SJed Brown 559b1a0a8a3SJed Brown EXTERN_C_BEGIN 560b1a0a8a3SJed Brown #undef __FUNCT__ 561f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetTotalSubdomains_GASM" 562ab3e923fSDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetTotalSubdomains_GASM(PC pc,PetscInt N) { 563f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 564b1a0a8a3SJed Brown PetscErrorCode ierr; 565b1a0a8a3SJed Brown PetscMPIInt rank,size; 566b1a0a8a3SJed Brown PetscInt n; 567b1a0a8a3SJed Brown 568b1a0a8a3SJed Brown PetscFunctionBegin; 569b1a0a8a3SJed Brown if (N < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of total blocks must be > 0, N = %D",N); 570b1a0a8a3SJed Brown 571b1a0a8a3SJed Brown /* 572b1a0a8a3SJed Brown Split the subdomains equally among all processors 573b1a0a8a3SJed Brown */ 574b1a0a8a3SJed Brown ierr = MPI_Comm_rank(((PetscObject)pc)->comm,&rank);CHKERRQ(ierr); 575b1a0a8a3SJed Brown ierr = MPI_Comm_size(((PetscObject)pc)->comm,&size);CHKERRQ(ierr); 576b1a0a8a3SJed Brown n = N/size + ((N % size) > rank); 577b1a0a8a3SJed Brown if (!n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Process %d must have at least one block: total processors %d total blocks %D",(int)rank,(int)size,N); 578f746d493SDmitry Karpeev if (pc->setupcalled && n != osm->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PCGASMSetTotalSubdomains() should be called before PCSetUp()."); 579b1a0a8a3SJed Brown if (!pc->setupcalled) { 580b1a0a8a3SJed Brown if (osm->is) { 581ab3e923fSDmitry Karpeev ierr = PCGASMDestroySubdomains(osm->n,osm->is,osm->is_local);CHKERRQ(ierr); 582b1a0a8a3SJed Brown } 583*93c1ec32SDmitry Karpeev osm->N = N; 584f746d493SDmitry Karpeev osm->n = n; 585b1a0a8a3SJed Brown osm->is = 0; 586b1a0a8a3SJed Brown osm->is_local = 0; 587b1a0a8a3SJed Brown } 588b1a0a8a3SJed Brown PetscFunctionReturn(0); 589ab3e923fSDmitry Karpeev }/* PCGASMSetTotalSubdomains_GASM() */ 590b1a0a8a3SJed Brown EXTERN_C_END 591b1a0a8a3SJed Brown 592b1a0a8a3SJed Brown EXTERN_C_BEGIN 593b1a0a8a3SJed Brown #undef __FUNCT__ 594f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetOverlap_GASM" 595f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetOverlap_GASM(PC pc,PetscInt ovl) 596b1a0a8a3SJed Brown { 597f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 598b1a0a8a3SJed Brown 599b1a0a8a3SJed Brown PetscFunctionBegin; 600b1a0a8a3SJed Brown if (ovl < 0) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Negative overlap value requested"); 601f746d493SDmitry Karpeev if (pc->setupcalled && ovl != osm->overlap) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"PCGASMSetOverlap() should be called before PCSetUp()."); 602b1a0a8a3SJed Brown if (!pc->setupcalled) { 603b1a0a8a3SJed Brown osm->overlap = ovl; 604b1a0a8a3SJed Brown } 605b1a0a8a3SJed Brown PetscFunctionReturn(0); 606b1a0a8a3SJed Brown } 607b1a0a8a3SJed Brown EXTERN_C_END 608b1a0a8a3SJed Brown 609b1a0a8a3SJed Brown EXTERN_C_BEGIN 610b1a0a8a3SJed Brown #undef __FUNCT__ 611f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetType_GASM" 612f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetType_GASM(PC pc,PCGASMType type) 613b1a0a8a3SJed Brown { 614f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 615b1a0a8a3SJed Brown 616b1a0a8a3SJed Brown PetscFunctionBegin; 617b1a0a8a3SJed Brown osm->type = type; 618b1a0a8a3SJed Brown osm->type_set = PETSC_TRUE; 619b1a0a8a3SJed Brown PetscFunctionReturn(0); 620b1a0a8a3SJed Brown } 621b1a0a8a3SJed Brown EXTERN_C_END 622b1a0a8a3SJed Brown 623b1a0a8a3SJed Brown EXTERN_C_BEGIN 624b1a0a8a3SJed Brown #undef __FUNCT__ 625f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetSortIndices_GASM" 626f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetSortIndices_GASM(PC pc,PetscBool doSort) 627b1a0a8a3SJed Brown { 628f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 629b1a0a8a3SJed Brown 630b1a0a8a3SJed Brown PetscFunctionBegin; 631b1a0a8a3SJed Brown osm->sort_indices = doSort; 632b1a0a8a3SJed Brown PetscFunctionReturn(0); 633b1a0a8a3SJed Brown } 634b1a0a8a3SJed Brown EXTERN_C_END 635b1a0a8a3SJed Brown 636b1a0a8a3SJed Brown EXTERN_C_BEGIN 637b1a0a8a3SJed Brown #undef __FUNCT__ 638f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMGetSubKSP_GASM" 63944fe18e5SDmitry Karpeev /* 64044fe18e5SDmitry Karpeev FIX: This routine might need to be modified once multiple ranks per subdomain are allowed. 64144fe18e5SDmitry Karpeev In particular, it would upset the global subdomain number calculation. 64244fe18e5SDmitry Karpeev */ 643ab3e923fSDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMGetSubKSP_GASM(PC pc,PetscInt *n,PetscInt *first,KSP **ksp) 644b1a0a8a3SJed Brown { 645f746d493SDmitry Karpeev PC_GASM *osm = (PC_GASM*)pc->data; 646b1a0a8a3SJed Brown PetscErrorCode ierr; 647b1a0a8a3SJed Brown 648b1a0a8a3SJed Brown PetscFunctionBegin; 649ab3e923fSDmitry Karpeev if (osm->n < 1) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ORDER,"Need to call PCSetUP() on PC (or KSPSetUp() on the outer KSP object) before calling here"); 650b1a0a8a3SJed Brown 651ab3e923fSDmitry Karpeev if (n) { 652ab3e923fSDmitry Karpeev *n = osm->n; 653b1a0a8a3SJed Brown } 654ab3e923fSDmitry Karpeev if (first) { 655ab3e923fSDmitry Karpeev ierr = MPI_Scan(&osm->n,first,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr); 656ab3e923fSDmitry Karpeev *first -= osm->n; 657b1a0a8a3SJed Brown } 658b1a0a8a3SJed Brown if (ksp) { 659b1a0a8a3SJed Brown /* Assume that local solves are now different; not necessarily 660f746d493SDmitry Karpeev true though! This flag is used only for PCView_GASM() */ 661b1a0a8a3SJed Brown *ksp = osm->ksp; 662b1a0a8a3SJed Brown osm->same_local_solves = PETSC_FALSE; 663b1a0a8a3SJed Brown } 664b1a0a8a3SJed Brown PetscFunctionReturn(0); 665ab3e923fSDmitry Karpeev }/* PCGASMGetSubKSP_GASM() */ 666b1a0a8a3SJed Brown EXTERN_C_END 667b1a0a8a3SJed Brown 668b1a0a8a3SJed Brown 669b1a0a8a3SJed Brown #undef __FUNCT__ 670f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetLocalSubdomains" 671b1a0a8a3SJed Brown /*@C 672f746d493SDmitry Karpeev PCGASMSetLocalSubdomains - Sets the local subdomains (for this processor 673b1a0a8a3SJed Brown only) for the additive Schwarz preconditioner. 674b1a0a8a3SJed Brown 675b1a0a8a3SJed Brown Collective on PC 676b1a0a8a3SJed Brown 677b1a0a8a3SJed Brown Input Parameters: 678b1a0a8a3SJed Brown + pc - the preconditioner context 679b1a0a8a3SJed Brown . n - the number of subdomains for this processor (default value = 1) 680b1a0a8a3SJed Brown . is - the index set that defines the subdomains for this processor 681b1a0a8a3SJed Brown (or PETSC_NULL for PETSc to determine subdomains) 682b1a0a8a3SJed Brown - is_local - the index sets that define the local part of the subdomains for this processor 683b1a0a8a3SJed Brown (or PETSC_NULL to use the default of 1 subdomain per process) 684b1a0a8a3SJed Brown 685b1a0a8a3SJed Brown Notes: 686b1a0a8a3SJed Brown The IS numbering is in the parallel, global numbering of the vector. 687b1a0a8a3SJed Brown 688f746d493SDmitry Karpeev By default the GASM preconditioner uses 1 block per processor. 689b1a0a8a3SJed Brown 690f746d493SDmitry Karpeev Use PCGASMSetTotalSubdomains() to set the subdomains for all processors. 691b1a0a8a3SJed Brown 692b1a0a8a3SJed Brown Level: advanced 693b1a0a8a3SJed Brown 694f746d493SDmitry Karpeev .keywords: PC, GASM, set, local, subdomains, additive Schwarz 695b1a0a8a3SJed Brown 696f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetOverlap(), PCGASMGetSubKSP(), 697f746d493SDmitry Karpeev PCGASMCreateSubdomains2D(), PCGASMGetLocalSubdomains() 698b1a0a8a3SJed Brown @*/ 699f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetLocalSubdomains(PC pc,PetscInt n,IS is[],IS is_local[]) 700b1a0a8a3SJed Brown { 701b1a0a8a3SJed Brown PetscErrorCode ierr; 702b1a0a8a3SJed Brown 703b1a0a8a3SJed Brown PetscFunctionBegin; 704b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 705f746d493SDmitry Karpeev ierr = PetscTryMethod(pc,"PCGASMSetLocalSubdomains_C",(PC,PetscInt,IS[],IS[]),(pc,n,is,is_local));CHKERRQ(ierr); 706b1a0a8a3SJed Brown PetscFunctionReturn(0); 707b1a0a8a3SJed Brown } 708b1a0a8a3SJed Brown 709b1a0a8a3SJed Brown #undef __FUNCT__ 710f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetTotalSubdomains" 711b1a0a8a3SJed Brown /*@C 712f746d493SDmitry Karpeev PCGASMSetTotalSubdomains - Sets the subdomains for all processor for the 713b1a0a8a3SJed Brown additive Schwarz preconditioner. Either all or no processors in the 714b1a0a8a3SJed Brown PC communicator must call this routine, with the same index sets. 715b1a0a8a3SJed Brown 716b1a0a8a3SJed Brown Collective on PC 717b1a0a8a3SJed Brown 718b1a0a8a3SJed Brown Input Parameters: 719b1a0a8a3SJed Brown + pc - the preconditioner context 720b1a0a8a3SJed Brown . n - the number of subdomains for all processors 721b1a0a8a3SJed Brown . is - the index sets that define the subdomains for all processor 722b1a0a8a3SJed Brown (or PETSC_NULL for PETSc to determine subdomains) 723b1a0a8a3SJed Brown - is_local - the index sets that define the local part of the subdomains for this processor 724b1a0a8a3SJed Brown (or PETSC_NULL to use the default of 1 subdomain per process) 725b1a0a8a3SJed Brown 726b1a0a8a3SJed Brown Options Database Key: 727b1a0a8a3SJed Brown To set the total number of subdomain blocks rather than specify the 728b1a0a8a3SJed Brown index sets, use the option 729f746d493SDmitry Karpeev . -pc_gasm_blocks <blks> - Sets total blocks 730b1a0a8a3SJed Brown 731b1a0a8a3SJed Brown Notes: 732b1a0a8a3SJed Brown Currently you cannot use this to set the actual subdomains with the argument is. 733b1a0a8a3SJed Brown 734f746d493SDmitry Karpeev By default the GASM preconditioner uses 1 block per processor. 735b1a0a8a3SJed Brown 736b1a0a8a3SJed Brown These index sets cannot be destroyed until after completion of the 737f746d493SDmitry Karpeev linear solves for which the GASM preconditioner is being used. 738b1a0a8a3SJed Brown 739f746d493SDmitry Karpeev Use PCGASMSetLocalSubdomains() to set local subdomains. 740b1a0a8a3SJed Brown 741b1a0a8a3SJed Brown Level: advanced 742b1a0a8a3SJed Brown 743f746d493SDmitry Karpeev .keywords: PC, GASM, set, total, global, subdomains, additive Schwarz 744b1a0a8a3SJed Brown 745f746d493SDmitry Karpeev .seealso: PCGASMSetLocalSubdomains(), PCGASMSetOverlap(), PCGASMGetSubKSP(), 746f746d493SDmitry Karpeev PCGASMCreateSubdomains2D() 747b1a0a8a3SJed Brown @*/ 748f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetTotalSubdomains(PC pc,PetscInt N) 749b1a0a8a3SJed Brown { 750b1a0a8a3SJed Brown PetscErrorCode ierr; 751b1a0a8a3SJed Brown 752b1a0a8a3SJed Brown PetscFunctionBegin; 753b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 754f746d493SDmitry Karpeev ierr = PetscTryMethod(pc,"PCGASMSetTotalSubdomains_C",(PC,PetscInt),(pc,N));CHKERRQ(ierr); 755b1a0a8a3SJed Brown PetscFunctionReturn(0); 756b1a0a8a3SJed Brown } 757b1a0a8a3SJed Brown 758b1a0a8a3SJed Brown #undef __FUNCT__ 759f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetOverlap" 760b1a0a8a3SJed Brown /*@ 761f746d493SDmitry Karpeev PCGASMSetOverlap - Sets the overlap between a pair of subdomains for the 762b1a0a8a3SJed Brown additive Schwarz preconditioner. Either all or no processors in the 763b1a0a8a3SJed Brown PC communicator must call this routine. 764b1a0a8a3SJed Brown 765b1a0a8a3SJed Brown Logically Collective on PC 766b1a0a8a3SJed Brown 767b1a0a8a3SJed Brown Input Parameters: 768b1a0a8a3SJed Brown + pc - the preconditioner context 769b1a0a8a3SJed Brown - ovl - the amount of overlap between subdomains (ovl >= 0, default value = 1) 770b1a0a8a3SJed Brown 771b1a0a8a3SJed Brown Options Database Key: 772f746d493SDmitry Karpeev . -pc_gasm_overlap <ovl> - Sets overlap 773b1a0a8a3SJed Brown 774b1a0a8a3SJed Brown Notes: 775f746d493SDmitry Karpeev By default the GASM preconditioner uses 1 block per processor. To use 776f746d493SDmitry Karpeev multiple blocks per perocessor, see PCGASMSetTotalSubdomains() and 777f746d493SDmitry Karpeev PCGASMSetLocalSubdomains() (and the option -pc_gasm_blocks <blks>). 778b1a0a8a3SJed Brown 779b1a0a8a3SJed Brown The overlap defaults to 1, so if one desires that no additional 780b1a0a8a3SJed Brown overlap be computed beyond what may have been set with a call to 781f746d493SDmitry Karpeev PCGASMSetTotalSubdomains() or PCGASMSetLocalSubdomains(), then ovl 782b1a0a8a3SJed Brown must be set to be 0. In particular, if one does not explicitly set 783b1a0a8a3SJed Brown the subdomains an application code, then all overlap would be computed 784f746d493SDmitry Karpeev internally by PETSc, and using an overlap of 0 would result in an GASM 785b1a0a8a3SJed Brown variant that is equivalent to the block Jacobi preconditioner. 786b1a0a8a3SJed Brown 787b1a0a8a3SJed Brown Note that one can define initial index sets with any overlap via 788f746d493SDmitry Karpeev PCGASMSetTotalSubdomains() or PCGASMSetLocalSubdomains(); the routine 789f746d493SDmitry Karpeev PCGASMSetOverlap() merely allows PETSc to extend that overlap further 790b1a0a8a3SJed Brown if desired. 791b1a0a8a3SJed Brown 792b1a0a8a3SJed Brown Level: intermediate 793b1a0a8a3SJed Brown 794f746d493SDmitry Karpeev .keywords: PC, GASM, set, overlap 795b1a0a8a3SJed Brown 796f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetLocalSubdomains(), PCGASMGetSubKSP(), 797f746d493SDmitry Karpeev PCGASMCreateSubdomains2D(), PCGASMGetLocalSubdomains() 798b1a0a8a3SJed Brown @*/ 799f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetOverlap(PC pc,PetscInt ovl) 800b1a0a8a3SJed Brown { 801b1a0a8a3SJed Brown PetscErrorCode ierr; 802b1a0a8a3SJed Brown 803b1a0a8a3SJed Brown PetscFunctionBegin; 804b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 805b1a0a8a3SJed Brown PetscValidLogicalCollectiveInt(pc,ovl,2); 806f746d493SDmitry Karpeev ierr = PetscTryMethod(pc,"PCGASMSetOverlap_C",(PC,PetscInt),(pc,ovl));CHKERRQ(ierr); 807b1a0a8a3SJed Brown PetscFunctionReturn(0); 808b1a0a8a3SJed Brown } 809b1a0a8a3SJed Brown 810b1a0a8a3SJed Brown #undef __FUNCT__ 811f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetType" 812b1a0a8a3SJed Brown /*@ 813f746d493SDmitry Karpeev PCGASMSetType - Sets the type of restriction and interpolation used 814b1a0a8a3SJed Brown for local problems in the additive Schwarz method. 815b1a0a8a3SJed Brown 816b1a0a8a3SJed Brown Logically Collective on PC 817b1a0a8a3SJed Brown 818b1a0a8a3SJed Brown Input Parameters: 819b1a0a8a3SJed Brown + pc - the preconditioner context 820f746d493SDmitry Karpeev - type - variant of GASM, one of 821b1a0a8a3SJed Brown .vb 822f746d493SDmitry Karpeev PC_GASM_BASIC - full interpolation and restriction 823f746d493SDmitry Karpeev PC_GASM_RESTRICT - full restriction, local processor interpolation 824f746d493SDmitry Karpeev PC_GASM_INTERPOLATE - full interpolation, local processor restriction 825f746d493SDmitry Karpeev PC_GASM_NONE - local processor restriction and interpolation 826b1a0a8a3SJed Brown .ve 827b1a0a8a3SJed Brown 828b1a0a8a3SJed Brown Options Database Key: 829f746d493SDmitry Karpeev . -pc_gasm_type [basic,restrict,interpolate,none] - Sets GASM type 830b1a0a8a3SJed Brown 831b1a0a8a3SJed Brown Level: intermediate 832b1a0a8a3SJed Brown 833f746d493SDmitry Karpeev .keywords: PC, GASM, set, type 834b1a0a8a3SJed Brown 835f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetTotalSubdomains(), PCGASMGetSubKSP(), 836f746d493SDmitry Karpeev PCGASMCreateSubdomains2D() 837b1a0a8a3SJed Brown @*/ 838f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetType(PC pc,PCGASMType type) 839b1a0a8a3SJed Brown { 840b1a0a8a3SJed Brown PetscErrorCode ierr; 841b1a0a8a3SJed Brown 842b1a0a8a3SJed Brown PetscFunctionBegin; 843b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 844b1a0a8a3SJed Brown PetscValidLogicalCollectiveEnum(pc,type,2); 845f746d493SDmitry Karpeev ierr = PetscTryMethod(pc,"PCGASMSetType_C",(PC,PCGASMType),(pc,type));CHKERRQ(ierr); 846b1a0a8a3SJed Brown PetscFunctionReturn(0); 847b1a0a8a3SJed Brown } 848b1a0a8a3SJed Brown 849b1a0a8a3SJed Brown #undef __FUNCT__ 850f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMSetSortIndices" 851b1a0a8a3SJed Brown /*@ 852f746d493SDmitry Karpeev PCGASMSetSortIndices - Determines whether subdomain indices are sorted. 853b1a0a8a3SJed Brown 854b1a0a8a3SJed Brown Logically Collective on PC 855b1a0a8a3SJed Brown 856b1a0a8a3SJed Brown Input Parameters: 857b1a0a8a3SJed Brown + pc - the preconditioner context 858b1a0a8a3SJed Brown - doSort - sort the subdomain indices 859b1a0a8a3SJed Brown 860b1a0a8a3SJed Brown Level: intermediate 861b1a0a8a3SJed Brown 862f746d493SDmitry Karpeev .keywords: PC, GASM, set, type 863b1a0a8a3SJed Brown 864f746d493SDmitry Karpeev .seealso: PCGASMSetLocalSubdomains(), PCGASMSetTotalSubdomains(), PCGASMGetSubKSP(), 865f746d493SDmitry Karpeev PCGASMCreateSubdomains2D() 866b1a0a8a3SJed Brown @*/ 867f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMSetSortIndices(PC pc,PetscBool doSort) 868b1a0a8a3SJed Brown { 869b1a0a8a3SJed Brown PetscErrorCode ierr; 870b1a0a8a3SJed Brown 871b1a0a8a3SJed Brown PetscFunctionBegin; 872b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 873b1a0a8a3SJed Brown PetscValidLogicalCollectiveBool(pc,doSort,2); 874f746d493SDmitry Karpeev ierr = PetscTryMethod(pc,"PCGASMSetSortIndices_C",(PC,PetscBool),(pc,doSort));CHKERRQ(ierr); 875b1a0a8a3SJed Brown PetscFunctionReturn(0); 876b1a0a8a3SJed Brown } 877b1a0a8a3SJed Brown 878b1a0a8a3SJed Brown #undef __FUNCT__ 879f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMGetSubKSP" 880b1a0a8a3SJed Brown /*@C 881f746d493SDmitry Karpeev PCGASMGetSubKSP - Gets the local KSP contexts for all blocks on 882b1a0a8a3SJed Brown this processor. 883b1a0a8a3SJed Brown 884b1a0a8a3SJed Brown Collective on PC iff first_local is requested 885b1a0a8a3SJed Brown 886b1a0a8a3SJed Brown Input Parameter: 887b1a0a8a3SJed Brown . pc - the preconditioner context 888b1a0a8a3SJed Brown 889b1a0a8a3SJed Brown Output Parameters: 890b1a0a8a3SJed Brown + n_local - the number of blocks on this processor or PETSC_NULL 891b1a0a8a3SJed Brown . first_local - the global number of the first block on this processor or PETSC_NULL, 892b1a0a8a3SJed Brown all processors must request or all must pass PETSC_NULL 893b1a0a8a3SJed Brown - ksp - the array of KSP contexts 894b1a0a8a3SJed Brown 895b1a0a8a3SJed Brown Note: 896f746d493SDmitry Karpeev After PCGASMGetSubKSP() the array of KSPes is not to be freed 897b1a0a8a3SJed Brown 898b1a0a8a3SJed Brown Currently for some matrix implementations only 1 block per processor 899b1a0a8a3SJed Brown is supported. 900b1a0a8a3SJed Brown 901f746d493SDmitry Karpeev You must call KSPSetUp() before calling PCGASMGetSubKSP(). 902b1a0a8a3SJed Brown 903b1a0a8a3SJed Brown Level: advanced 904b1a0a8a3SJed Brown 905f746d493SDmitry Karpeev .keywords: PC, GASM, additive Schwarz, get, sub, KSP, context 906b1a0a8a3SJed Brown 907f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetTotalSubdomains(), PCGASMSetOverlap(), 908f746d493SDmitry Karpeev PCGASMCreateSubdomains2D(), 909b1a0a8a3SJed Brown @*/ 910f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[]) 911b1a0a8a3SJed Brown { 912b1a0a8a3SJed Brown PetscErrorCode ierr; 913b1a0a8a3SJed Brown 914b1a0a8a3SJed Brown PetscFunctionBegin; 915b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 916f746d493SDmitry Karpeev ierr = PetscUseMethod(pc,"PCGASMGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp));CHKERRQ(ierr); 917b1a0a8a3SJed Brown PetscFunctionReturn(0); 918b1a0a8a3SJed Brown } 919b1a0a8a3SJed Brown 920b1a0a8a3SJed Brown /* -------------------------------------------------------------------------------------*/ 921b1a0a8a3SJed Brown /*MC 922f746d493SDmitry Karpeev PCGASM - Use the (restricted) additive Schwarz method, each block is (approximately) solved with 923b1a0a8a3SJed Brown its own KSP object. 924b1a0a8a3SJed Brown 925b1a0a8a3SJed Brown Options Database Keys: 926f746d493SDmitry Karpeev + -pc_gasm_truelocal - Activates PCGGASMSetUseTrueLocal() 927f746d493SDmitry Karpeev . -pc_gasm_blocks <blks> - Sets total blocks 928f746d493SDmitry Karpeev . -pc_gasm_overlap <ovl> - Sets overlap 929f746d493SDmitry Karpeev - -pc_gasm_type [basic,restrict,interpolate,none] - Sets GASM type 930b1a0a8a3SJed Brown 931b1a0a8a3SJed Brown IMPORTANT: If you run with, for example, 3 blocks on 1 processor or 3 blocks on 3 processors you 932f746d493SDmitry Karpeev will get a different convergence rate due to the default option of -pc_gasm_type restrict. Use 933f746d493SDmitry Karpeev -pc_gasm_type basic to use the standard GASM. 934b1a0a8a3SJed Brown 935b1a0a8a3SJed Brown Notes: Each processor can have one or more blocks, but a block cannot be shared by more 936b1a0a8a3SJed Brown than one processor. Defaults to one block per processor. 937b1a0a8a3SJed Brown 938b1a0a8a3SJed Brown To set options on the solvers for each block append -sub_ to all the KSP, and PC 939b1a0a8a3SJed Brown options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly 940b1a0a8a3SJed Brown 941f746d493SDmitry Karpeev To set the options on the solvers separate for each block call PCGASMGetSubKSP() 942b1a0a8a3SJed Brown and set the options directly on the resulting KSP object (you can access its PC 943b1a0a8a3SJed Brown with KSPGetPC()) 944b1a0a8a3SJed Brown 945b1a0a8a3SJed Brown 946b1a0a8a3SJed Brown Level: beginner 947b1a0a8a3SJed Brown 948b1a0a8a3SJed Brown Concepts: additive Schwarz method 949b1a0a8a3SJed Brown 950b1a0a8a3SJed Brown References: 951b1a0a8a3SJed Brown An additive variant of the Schwarz alternating method for the case of many subregions 952b1a0a8a3SJed Brown M Dryja, OB Widlund - Courant Institute, New York University Technical report 953b1a0a8a3SJed Brown 954b1a0a8a3SJed Brown Domain Decompositions: Parallel Multilevel Methods for Elliptic Partial Differential Equations, 955b1a0a8a3SJed Brown Barry Smith, Petter Bjorstad, and William Gropp, Cambridge University Press, ISBN 0-521-49589-X. 956b1a0a8a3SJed Brown 957b1a0a8a3SJed Brown .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 958f746d493SDmitry Karpeev PCBJACOBI, PCGASMSetUseTrueLocal(), PCGASMGetSubKSP(), PCGASMSetLocalSubdomains(), 959f746d493SDmitry Karpeev PCGASMSetTotalSubdomains(), PCSetModifySubmatrices(), PCGASMSetOverlap(), PCGASMSetType() 960b1a0a8a3SJed Brown 961b1a0a8a3SJed Brown M*/ 962b1a0a8a3SJed Brown 963b1a0a8a3SJed Brown EXTERN_C_BEGIN 964b1a0a8a3SJed Brown #undef __FUNCT__ 965f746d493SDmitry Karpeev #define __FUNCT__ "PCCreate_GASM" 966f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_GASM(PC pc) 967b1a0a8a3SJed Brown { 968b1a0a8a3SJed Brown PetscErrorCode ierr; 969f746d493SDmitry Karpeev PC_GASM *osm; 970b1a0a8a3SJed Brown 971b1a0a8a3SJed Brown PetscFunctionBegin; 972f746d493SDmitry Karpeev ierr = PetscNewLog(pc,PC_GASM,&osm);CHKERRQ(ierr); 973ab3e923fSDmitry Karpeev osm->N = PETSC_DECIDE; 974ab3e923fSDmitry Karpeev osm->n = 0; 975ab3e923fSDmitry Karpeev osm->nmax = 0; 976b1a0a8a3SJed Brown osm->overlap = 1; 977b1a0a8a3SJed Brown osm->ksp = 0; 978ab3e923fSDmitry Karpeev osm->grestriction = 0; 979ab3e923fSDmitry Karpeev osm->gprolongation = 0; 980ab3e923fSDmitry Karpeev osm->gx = 0; 981ab3e923fSDmitry Karpeev osm->gy = 0; 982b1a0a8a3SJed Brown osm->x = 0; 983b1a0a8a3SJed Brown osm->y = 0; 984b1a0a8a3SJed Brown osm->is = 0; 985b1a0a8a3SJed Brown osm->is_local = 0; 986b1a0a8a3SJed Brown osm->pmat = 0; 987f746d493SDmitry Karpeev osm->type = PC_GASM_RESTRICT; 988b1a0a8a3SJed Brown osm->same_local_solves = PETSC_TRUE; 989b1a0a8a3SJed Brown osm->sort_indices = PETSC_TRUE; 990b1a0a8a3SJed Brown 991b1a0a8a3SJed Brown pc->data = (void*)osm; 992f746d493SDmitry Karpeev pc->ops->apply = PCApply_GASM; 993f746d493SDmitry Karpeev pc->ops->applytranspose = PCApplyTranspose_GASM; 994f746d493SDmitry Karpeev pc->ops->setup = PCSetUp_GASM; 995f746d493SDmitry Karpeev pc->ops->destroy = PCDestroy_GASM; 996f746d493SDmitry Karpeev pc->ops->setfromoptions = PCSetFromOptions_GASM; 997f746d493SDmitry Karpeev pc->ops->setuponblocks = PCSetUpOnBlocks_GASM; 998f746d493SDmitry Karpeev pc->ops->view = PCView_GASM; 999b1a0a8a3SJed Brown pc->ops->applyrichardson = 0; 1000b1a0a8a3SJed Brown 1001f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMSetLocalSubdomains_C","PCGASMSetLocalSubdomains_GASM", 1002f746d493SDmitry Karpeev PCGASMSetLocalSubdomains_GASM);CHKERRQ(ierr); 1003f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMSetTotalSubdomains_C","PCGASMSetTotalSubdomains_GASM", 1004f746d493SDmitry Karpeev PCGASMSetTotalSubdomains_GASM);CHKERRQ(ierr); 1005f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMSetOverlap_C","PCGASMSetOverlap_GASM", 1006f746d493SDmitry Karpeev PCGASMSetOverlap_GASM);CHKERRQ(ierr); 1007f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMSetType_C","PCGASMSetType_GASM", 1008f746d493SDmitry Karpeev PCGASMSetType_GASM);CHKERRQ(ierr); 1009f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMSetSortIndices_C","PCGASMSetSortIndices_GASM", 1010f746d493SDmitry Karpeev PCGASMSetSortIndices_GASM);CHKERRQ(ierr); 1011f746d493SDmitry Karpeev ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCGASMGetSubKSP_C","PCGASMGetSubKSP_GASM", 1012f746d493SDmitry Karpeev PCGASMGetSubKSP_GASM);CHKERRQ(ierr); 1013b1a0a8a3SJed Brown PetscFunctionReturn(0); 1014b1a0a8a3SJed Brown } 1015b1a0a8a3SJed Brown EXTERN_C_END 1016b1a0a8a3SJed Brown 1017b1a0a8a3SJed Brown 1018b1a0a8a3SJed Brown #undef __FUNCT__ 1019f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMCreateSubdomains" 1020b1a0a8a3SJed Brown /*@C 1021f746d493SDmitry Karpeev PCGASMCreateSubdomains - Creates the index sets for the overlapping Schwarz 1022b1a0a8a3SJed Brown preconditioner for a any problem on a general grid. 1023b1a0a8a3SJed Brown 1024b1a0a8a3SJed Brown Collective 1025b1a0a8a3SJed Brown 1026b1a0a8a3SJed Brown Input Parameters: 1027b1a0a8a3SJed Brown + A - The global matrix operator 1028b1a0a8a3SJed Brown - n - the number of local blocks 1029b1a0a8a3SJed Brown 1030b1a0a8a3SJed Brown Output Parameters: 1031b1a0a8a3SJed Brown . outis - the array of index sets defining the subdomains 1032b1a0a8a3SJed Brown 1033b1a0a8a3SJed Brown Level: advanced 1034b1a0a8a3SJed Brown 1035f746d493SDmitry Karpeev Note: this generates nonoverlapping subdomains; the PCGASM will generate the overlap 1036f746d493SDmitry Karpeev from these if you use PCGASMSetLocalSubdomains() 1037b1a0a8a3SJed Brown 1038b1a0a8a3SJed Brown In the Fortran version you must provide the array outis[] already allocated of length n. 1039b1a0a8a3SJed Brown 1040f746d493SDmitry Karpeev .keywords: PC, GASM, additive Schwarz, create, subdomains, unstructured grid 1041b1a0a8a3SJed Brown 1042f746d493SDmitry Karpeev .seealso: PCGASMSetLocalSubdomains(), PCGASMDestroySubdomains() 1043b1a0a8a3SJed Brown @*/ 1044f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMCreateSubdomains(Mat A, PetscInt n, IS* outis[]) 1045b1a0a8a3SJed Brown { 1046b1a0a8a3SJed Brown MatPartitioning mpart; 1047b1a0a8a3SJed Brown const char *prefix; 1048b1a0a8a3SJed Brown PetscErrorCode (*f)(Mat,PetscBool *,MatReuse,Mat*); 1049b1a0a8a3SJed Brown PetscMPIInt size; 1050b1a0a8a3SJed Brown PetscInt i,j,rstart,rend,bs; 1051b1a0a8a3SJed Brown PetscBool iscopy = PETSC_FALSE,isbaij = PETSC_FALSE,foundpart = PETSC_FALSE; 1052b1a0a8a3SJed Brown Mat Ad = PETSC_NULL, adj; 1053b1a0a8a3SJed Brown IS ispart,isnumb,*is; 1054b1a0a8a3SJed Brown PetscErrorCode ierr; 1055b1a0a8a3SJed Brown 1056b1a0a8a3SJed Brown PetscFunctionBegin; 1057b1a0a8a3SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1058b1a0a8a3SJed Brown PetscValidPointer(outis,3); 1059b1a0a8a3SJed Brown if (n < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of local blocks must be > 0, n = %D",n); 1060b1a0a8a3SJed Brown 1061b1a0a8a3SJed Brown /* Get prefix, row distribution, and block size */ 1062b1a0a8a3SJed Brown ierr = MatGetOptionsPrefix(A,&prefix);CHKERRQ(ierr); 1063b1a0a8a3SJed Brown ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); 1064b1a0a8a3SJed Brown ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1065b1a0a8a3SJed Brown if (rstart/bs*bs != rstart || rend/bs*bs != rend) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"bad row distribution [%D,%D) for matrix block size %D",rstart,rend,bs); 1066b1a0a8a3SJed Brown 1067b1a0a8a3SJed Brown /* Get diagonal block from matrix if possible */ 1068b1a0a8a3SJed Brown ierr = MPI_Comm_size(((PetscObject)A)->comm,&size);CHKERRQ(ierr); 1069b1a0a8a3SJed Brown ierr = PetscObjectQueryFunction((PetscObject)A,"MatGetDiagonalBlock_C",(void (**)(void))&f);CHKERRQ(ierr); 1070b1a0a8a3SJed Brown if (f) { 1071b1a0a8a3SJed Brown ierr = (*f)(A,&iscopy,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr); 1072b1a0a8a3SJed Brown } else if (size == 1) { 1073b1a0a8a3SJed Brown iscopy = PETSC_FALSE; Ad = A; 1074b1a0a8a3SJed Brown } else { 1075b1a0a8a3SJed Brown iscopy = PETSC_FALSE; Ad = PETSC_NULL; 1076b1a0a8a3SJed Brown } 1077b1a0a8a3SJed Brown if (Ad) { 1078b1a0a8a3SJed Brown ierr = PetscTypeCompare((PetscObject)Ad,MATSEQBAIJ,&isbaij);CHKERRQ(ierr); 1079b1a0a8a3SJed Brown if (!isbaij) {ierr = PetscTypeCompare((PetscObject)Ad,MATSEQSBAIJ,&isbaij);CHKERRQ(ierr);} 1080b1a0a8a3SJed Brown } 1081b1a0a8a3SJed Brown if (Ad && n > 1) { 1082b1a0a8a3SJed Brown PetscBool match,done; 1083b1a0a8a3SJed Brown /* Try to setup a good matrix partitioning if available */ 1084b1a0a8a3SJed Brown ierr = MatPartitioningCreate(PETSC_COMM_SELF,&mpart);CHKERRQ(ierr); 1085b1a0a8a3SJed Brown ierr = PetscObjectSetOptionsPrefix((PetscObject)mpart,prefix);CHKERRQ(ierr); 1086b1a0a8a3SJed Brown ierr = MatPartitioningSetFromOptions(mpart);CHKERRQ(ierr); 1087b1a0a8a3SJed Brown ierr = PetscTypeCompare((PetscObject)mpart,MATPARTITIONINGCURRENT,&match);CHKERRQ(ierr); 1088b1a0a8a3SJed Brown if (!match) { 1089b1a0a8a3SJed Brown ierr = PetscTypeCompare((PetscObject)mpart,MATPARTITIONINGSQUARE,&match);CHKERRQ(ierr); 1090b1a0a8a3SJed Brown } 1091b1a0a8a3SJed Brown if (!match) { /* assume a "good" partitioner is available */ 1092b1a0a8a3SJed Brown PetscInt na,*ia,*ja; 1093b1a0a8a3SJed Brown ierr = MatGetRowIJ(Ad,0,PETSC_TRUE,isbaij,&na,&ia,&ja,&done);CHKERRQ(ierr); 1094b1a0a8a3SJed Brown if (done) { 1095b1a0a8a3SJed Brown /* Build adjacency matrix by hand. Unfortunately a call to 1096b1a0a8a3SJed Brown MatConvert(Ad,MATMPIADJ,MAT_INITIAL_MATRIX,&adj) will 1097b1a0a8a3SJed Brown remove the block-aij structure and we cannot expect 1098b1a0a8a3SJed Brown MatPartitioning to split vertices as we need */ 1099b1a0a8a3SJed Brown PetscInt i,j,*row,len,nnz,cnt,*iia=0,*jja=0; 1100b1a0a8a3SJed Brown nnz = 0; 1101b1a0a8a3SJed Brown for (i=0; i<na; i++) { /* count number of nonzeros */ 1102b1a0a8a3SJed Brown len = ia[i+1] - ia[i]; 1103b1a0a8a3SJed Brown row = ja + ia[i]; 1104b1a0a8a3SJed Brown for (j=0; j<len; j++) { 1105b1a0a8a3SJed Brown if (row[j] == i) { /* don't count diagonal */ 1106b1a0a8a3SJed Brown len--; break; 1107b1a0a8a3SJed Brown } 1108b1a0a8a3SJed Brown } 1109b1a0a8a3SJed Brown nnz += len; 1110b1a0a8a3SJed Brown } 1111b1a0a8a3SJed Brown ierr = PetscMalloc((na+1)*sizeof(PetscInt),&iia);CHKERRQ(ierr); 1112b1a0a8a3SJed Brown ierr = PetscMalloc((nnz)*sizeof(PetscInt),&jja);CHKERRQ(ierr); 1113b1a0a8a3SJed Brown nnz = 0; 1114b1a0a8a3SJed Brown iia[0] = 0; 1115b1a0a8a3SJed Brown for (i=0; i<na; i++) { /* fill adjacency */ 1116b1a0a8a3SJed Brown cnt = 0; 1117b1a0a8a3SJed Brown len = ia[i+1] - ia[i]; 1118b1a0a8a3SJed Brown row = ja + ia[i]; 1119b1a0a8a3SJed Brown for (j=0; j<len; j++) { 1120b1a0a8a3SJed Brown if (row[j] != i) { /* if not diagonal */ 1121b1a0a8a3SJed Brown jja[nnz+cnt++] = row[j]; 1122b1a0a8a3SJed Brown } 1123b1a0a8a3SJed Brown } 1124b1a0a8a3SJed Brown nnz += cnt; 1125b1a0a8a3SJed Brown iia[i+1] = nnz; 1126b1a0a8a3SJed Brown } 1127b1a0a8a3SJed Brown /* Partitioning of the adjacency matrix */ 1128b1a0a8a3SJed Brown ierr = MatCreateMPIAdj(PETSC_COMM_SELF,na,na,iia,jja,PETSC_NULL,&adj);CHKERRQ(ierr); 1129b1a0a8a3SJed Brown ierr = MatPartitioningSetAdjacency(mpart,adj);CHKERRQ(ierr); 1130b1a0a8a3SJed Brown ierr = MatPartitioningSetNParts(mpart,n);CHKERRQ(ierr); 1131b1a0a8a3SJed Brown ierr = MatPartitioningApply(mpart,&ispart);CHKERRQ(ierr); 1132b1a0a8a3SJed Brown ierr = ISPartitioningToNumbering(ispart,&isnumb);CHKERRQ(ierr); 1133b1a0a8a3SJed Brown ierr = MatDestroy(adj);CHKERRQ(ierr); 1134b1a0a8a3SJed Brown foundpart = PETSC_TRUE; 1135b1a0a8a3SJed Brown } 1136b1a0a8a3SJed Brown ierr = MatRestoreRowIJ(Ad,0,PETSC_TRUE,isbaij,&na,&ia,&ja,&done);CHKERRQ(ierr); 1137b1a0a8a3SJed Brown } 1138b1a0a8a3SJed Brown ierr = MatPartitioningDestroy(mpart);CHKERRQ(ierr); 1139b1a0a8a3SJed Brown } 1140b1a0a8a3SJed Brown if (iscopy) {ierr = MatDestroy(Ad);CHKERRQ(ierr);} 1141b1a0a8a3SJed Brown 1142b1a0a8a3SJed Brown ierr = PetscMalloc(n*sizeof(IS),&is);CHKERRQ(ierr); 1143b1a0a8a3SJed Brown *outis = is; 1144b1a0a8a3SJed Brown 1145b1a0a8a3SJed Brown if (!foundpart) { 1146b1a0a8a3SJed Brown 1147b1a0a8a3SJed Brown /* Partitioning by contiguous chunks of rows */ 1148b1a0a8a3SJed Brown 1149b1a0a8a3SJed Brown PetscInt mbs = (rend-rstart)/bs; 1150b1a0a8a3SJed Brown PetscInt start = rstart; 1151b1a0a8a3SJed Brown for (i=0; i<n; i++) { 1152b1a0a8a3SJed Brown PetscInt count = (mbs/n + ((mbs % n) > i)) * bs; 1153b1a0a8a3SJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,count,start,1,&is[i]);CHKERRQ(ierr); 1154b1a0a8a3SJed Brown start += count; 1155b1a0a8a3SJed Brown } 1156b1a0a8a3SJed Brown 1157b1a0a8a3SJed Brown } else { 1158b1a0a8a3SJed Brown 1159b1a0a8a3SJed Brown /* Partitioning by adjacency of diagonal block */ 1160b1a0a8a3SJed Brown 1161b1a0a8a3SJed Brown const PetscInt *numbering; 1162b1a0a8a3SJed Brown PetscInt *count,nidx,*indices,*newidx,start=0; 1163b1a0a8a3SJed Brown /* Get node count in each partition */ 1164b1a0a8a3SJed Brown ierr = PetscMalloc(n*sizeof(PetscInt),&count);CHKERRQ(ierr); 1165b1a0a8a3SJed Brown ierr = ISPartitioningCount(ispart,n,count);CHKERRQ(ierr); 1166b1a0a8a3SJed Brown if (isbaij && bs > 1) { /* adjust for the block-aij case */ 1167b1a0a8a3SJed Brown for (i=0; i<n; i++) count[i] *= bs; 1168b1a0a8a3SJed Brown } 1169b1a0a8a3SJed Brown /* Build indices from node numbering */ 1170b1a0a8a3SJed Brown ierr = ISGetLocalSize(isnumb,&nidx);CHKERRQ(ierr); 1171b1a0a8a3SJed Brown ierr = PetscMalloc(nidx*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1172b1a0a8a3SJed Brown for (i=0; i<nidx; i++) indices[i] = i; /* needs to be initialized */ 1173b1a0a8a3SJed Brown ierr = ISGetIndices(isnumb,&numbering);CHKERRQ(ierr); 1174b1a0a8a3SJed Brown ierr = PetscSortIntWithPermutation(nidx,numbering,indices);CHKERRQ(ierr); 1175b1a0a8a3SJed Brown ierr = ISRestoreIndices(isnumb,&numbering);CHKERRQ(ierr); 1176b1a0a8a3SJed Brown if (isbaij && bs > 1) { /* adjust for the block-aij case */ 1177b1a0a8a3SJed Brown ierr = PetscMalloc(nidx*bs*sizeof(PetscInt),&newidx);CHKERRQ(ierr); 1178b1a0a8a3SJed Brown for (i=0; i<nidx; i++) 1179b1a0a8a3SJed Brown for (j=0; j<bs; j++) 1180b1a0a8a3SJed Brown newidx[i*bs+j] = indices[i]*bs + j; 1181b1a0a8a3SJed Brown ierr = PetscFree(indices);CHKERRQ(ierr); 1182b1a0a8a3SJed Brown nidx *= bs; 1183b1a0a8a3SJed Brown indices = newidx; 1184b1a0a8a3SJed Brown } 1185b1a0a8a3SJed Brown /* Shift to get global indices */ 1186b1a0a8a3SJed Brown for (i=0; i<nidx; i++) indices[i] += rstart; 1187b1a0a8a3SJed Brown 1188b1a0a8a3SJed Brown /* Build the index sets for each block */ 1189b1a0a8a3SJed Brown for (i=0; i<n; i++) { 1190b1a0a8a3SJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,count[i],&indices[start],PETSC_COPY_VALUES,&is[i]);CHKERRQ(ierr); 1191b1a0a8a3SJed Brown ierr = ISSort(is[i]);CHKERRQ(ierr); 1192b1a0a8a3SJed Brown start += count[i]; 1193b1a0a8a3SJed Brown } 1194b1a0a8a3SJed Brown 1195b1a0a8a3SJed Brown ierr = PetscFree(count); 1196b1a0a8a3SJed Brown ierr = PetscFree(indices); 1197b1a0a8a3SJed Brown ierr = ISDestroy(isnumb);CHKERRQ(ierr); 1198b1a0a8a3SJed Brown ierr = ISDestroy(ispart);CHKERRQ(ierr); 1199b1a0a8a3SJed Brown 1200b1a0a8a3SJed Brown } 1201b1a0a8a3SJed Brown 1202b1a0a8a3SJed Brown PetscFunctionReturn(0); 1203b1a0a8a3SJed Brown } 1204b1a0a8a3SJed Brown 1205b1a0a8a3SJed Brown #undef __FUNCT__ 1206f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMDestroySubdomains" 1207b1a0a8a3SJed Brown /*@C 1208f746d493SDmitry Karpeev PCGASMDestroySubdomains - Destroys the index sets created with 1209f746d493SDmitry Karpeev PCGASMCreateSubdomains(). Should be called after setting subdomains 1210f746d493SDmitry Karpeev with PCGASMSetLocalSubdomains(). 1211b1a0a8a3SJed Brown 1212b1a0a8a3SJed Brown Collective 1213b1a0a8a3SJed Brown 1214b1a0a8a3SJed Brown Input Parameters: 1215b1a0a8a3SJed Brown + n - the number of index sets 1216b1a0a8a3SJed Brown . is - the array of index sets 1217b1a0a8a3SJed Brown - is_local - the array of local index sets, can be PETSC_NULL 1218b1a0a8a3SJed Brown 1219b1a0a8a3SJed Brown Level: advanced 1220b1a0a8a3SJed Brown 1221f746d493SDmitry Karpeev .keywords: PC, GASM, additive Schwarz, create, subdomains, unstructured grid 1222b1a0a8a3SJed Brown 1223f746d493SDmitry Karpeev .seealso: PCGASMCreateSubdomains(), PCGASMSetLocalSubdomains() 1224b1a0a8a3SJed Brown @*/ 1225f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMDestroySubdomains(PetscInt n, IS is[], IS is_local[]) 1226b1a0a8a3SJed Brown { 1227b1a0a8a3SJed Brown PetscInt i; 1228b1a0a8a3SJed Brown PetscErrorCode ierr; 1229b1a0a8a3SJed Brown PetscFunctionBegin; 1230b1a0a8a3SJed Brown if (n <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"n must be > 0: n = %D",n); 1231b1a0a8a3SJed Brown PetscValidPointer(is,2); 1232b1a0a8a3SJed Brown for (i=0; i<n; i++) { ierr = ISDestroy(is[i]);CHKERRQ(ierr); } 1233b1a0a8a3SJed Brown ierr = PetscFree(is);CHKERRQ(ierr); 1234b1a0a8a3SJed Brown if (is_local) { 1235b1a0a8a3SJed Brown PetscValidPointer(is_local,3); 1236b1a0a8a3SJed Brown for (i=0; i<n; i++) { ierr = ISDestroy(is_local[i]);CHKERRQ(ierr); } 1237b1a0a8a3SJed Brown ierr = PetscFree(is_local);CHKERRQ(ierr); 1238b1a0a8a3SJed Brown } 1239b1a0a8a3SJed Brown PetscFunctionReturn(0); 1240b1a0a8a3SJed Brown } 1241b1a0a8a3SJed Brown 1242b1a0a8a3SJed Brown #undef __FUNCT__ 1243f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMCreateSubdomains2D" 1244b1a0a8a3SJed Brown /*@ 1245f746d493SDmitry Karpeev PCGASMCreateSubdomains2D - Creates the index sets for the overlapping Schwarz 1246b1a0a8a3SJed Brown preconditioner for a two-dimensional problem on a regular grid. 1247b1a0a8a3SJed Brown 1248b1a0a8a3SJed Brown Not Collective 1249b1a0a8a3SJed Brown 1250b1a0a8a3SJed Brown Input Parameters: 1251b1a0a8a3SJed Brown + m, n - the number of mesh points in the x and y directions 1252b1a0a8a3SJed Brown . M, N - the number of subdomains in the x and y directions 1253b1a0a8a3SJed Brown . dof - degrees of freedom per node 1254b1a0a8a3SJed Brown - overlap - overlap in mesh lines 1255b1a0a8a3SJed Brown 1256b1a0a8a3SJed Brown Output Parameters: 1257b1a0a8a3SJed Brown + Nsub - the number of subdomains created 1258b1a0a8a3SJed Brown . is - array of index sets defining overlapping (if overlap > 0) subdomains 1259b1a0a8a3SJed Brown - is_local - array of index sets defining non-overlapping subdomains 1260b1a0a8a3SJed Brown 1261b1a0a8a3SJed Brown Note: 1262b1a0a8a3SJed Brown Presently PCAMSCreateSubdomains2d() is valid only for sequential 1263b1a0a8a3SJed Brown preconditioners. More general related routines are 1264f746d493SDmitry Karpeev PCGASMSetTotalSubdomains() and PCGASMSetLocalSubdomains(). 1265b1a0a8a3SJed Brown 1266b1a0a8a3SJed Brown Level: advanced 1267b1a0a8a3SJed Brown 1268f746d493SDmitry Karpeev .keywords: PC, GASM, additive Schwarz, create, subdomains, 2D, regular grid 1269b1a0a8a3SJed Brown 1270f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetLocalSubdomains(), PCGASMGetSubKSP(), 1271f746d493SDmitry Karpeev PCGASMSetOverlap() 1272b1a0a8a3SJed Brown @*/ 1273f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMCreateSubdomains2D(PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt dof,PetscInt overlap,PetscInt *Nsub,IS **is,IS **is_local) 1274b1a0a8a3SJed Brown { 1275b1a0a8a3SJed Brown PetscInt i,j,height,width,ystart,xstart,yleft,yright,xleft,xright,loc_outer; 1276b1a0a8a3SJed Brown PetscErrorCode ierr; 1277b1a0a8a3SJed Brown PetscInt nidx,*idx,loc,ii,jj,count; 1278b1a0a8a3SJed Brown 1279b1a0a8a3SJed Brown PetscFunctionBegin; 1280b1a0a8a3SJed Brown if (dof != 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," "); 1281b1a0a8a3SJed Brown 1282b1a0a8a3SJed Brown *Nsub = N*M; 1283b1a0a8a3SJed Brown ierr = PetscMalloc((*Nsub)*sizeof(IS*),is);CHKERRQ(ierr); 1284b1a0a8a3SJed Brown ierr = PetscMalloc((*Nsub)*sizeof(IS*),is_local);CHKERRQ(ierr); 1285b1a0a8a3SJed Brown ystart = 0; 1286b1a0a8a3SJed Brown loc_outer = 0; 1287b1a0a8a3SJed Brown for (i=0; i<N; i++) { 1288b1a0a8a3SJed Brown height = n/N + ((n % N) > i); /* height of subdomain */ 1289b1a0a8a3SJed Brown if (height < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many N subdomains for mesh dimension n"); 1290b1a0a8a3SJed Brown yleft = ystart - overlap; if (yleft < 0) yleft = 0; 1291b1a0a8a3SJed Brown yright = ystart + height + overlap; if (yright > n) yright = n; 1292b1a0a8a3SJed Brown xstart = 0; 1293b1a0a8a3SJed Brown for (j=0; j<M; j++) { 1294b1a0a8a3SJed Brown width = m/M + ((m % M) > j); /* width of subdomain */ 1295b1a0a8a3SJed Brown if (width < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many M subdomains for mesh dimension m"); 1296b1a0a8a3SJed Brown xleft = xstart - overlap; if (xleft < 0) xleft = 0; 1297b1a0a8a3SJed Brown xright = xstart + width + overlap; if (xright > m) xright = m; 1298b1a0a8a3SJed Brown nidx = (xright - xleft)*(yright - yleft); 1299b1a0a8a3SJed Brown ierr = PetscMalloc(nidx*sizeof(PetscInt),&idx);CHKERRQ(ierr); 1300b1a0a8a3SJed Brown loc = 0; 1301b1a0a8a3SJed Brown for (ii=yleft; ii<yright; ii++) { 1302b1a0a8a3SJed Brown count = m*ii + xleft; 1303b1a0a8a3SJed Brown for (jj=xleft; jj<xright; jj++) { 1304b1a0a8a3SJed Brown idx[loc++] = count++; 1305b1a0a8a3SJed Brown } 1306b1a0a8a3SJed Brown } 1307b1a0a8a3SJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,(*is)+loc_outer);CHKERRQ(ierr); 1308b1a0a8a3SJed Brown if (overlap == 0) { 1309b1a0a8a3SJed Brown ierr = PetscObjectReference((PetscObject)(*is)[loc_outer]);CHKERRQ(ierr); 1310b1a0a8a3SJed Brown (*is_local)[loc_outer] = (*is)[loc_outer]; 1311b1a0a8a3SJed Brown } else { 1312b1a0a8a3SJed Brown for (loc=0,ii=ystart; ii<ystart+height; ii++) { 1313b1a0a8a3SJed Brown for (jj=xstart; jj<xstart+width; jj++) { 1314b1a0a8a3SJed Brown idx[loc++] = m*ii + jj; 1315b1a0a8a3SJed Brown } 1316b1a0a8a3SJed Brown } 1317b1a0a8a3SJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,loc,idx,PETSC_COPY_VALUES,*is_local+loc_outer);CHKERRQ(ierr); 1318b1a0a8a3SJed Brown } 1319b1a0a8a3SJed Brown ierr = PetscFree(idx);CHKERRQ(ierr); 1320b1a0a8a3SJed Brown xstart += width; 1321b1a0a8a3SJed Brown loc_outer++; 1322b1a0a8a3SJed Brown } 1323b1a0a8a3SJed Brown ystart += height; 1324b1a0a8a3SJed Brown } 1325b1a0a8a3SJed Brown for (i=0; i<*Nsub; i++) { ierr = ISSort((*is)[i]);CHKERRQ(ierr); } 1326b1a0a8a3SJed Brown PetscFunctionReturn(0); 1327b1a0a8a3SJed Brown } 1328b1a0a8a3SJed Brown 1329b1a0a8a3SJed Brown #undef __FUNCT__ 1330f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMGetLocalSubdomains" 1331b1a0a8a3SJed Brown /*@C 1332f746d493SDmitry Karpeev PCGASMGetLocalSubdomains - Gets the local subdomains (for this processor 1333b1a0a8a3SJed Brown only) for the additive Schwarz preconditioner. 1334b1a0a8a3SJed Brown 1335b1a0a8a3SJed Brown Not Collective 1336b1a0a8a3SJed Brown 1337b1a0a8a3SJed Brown Input Parameter: 1338b1a0a8a3SJed Brown . pc - the preconditioner context 1339b1a0a8a3SJed Brown 1340b1a0a8a3SJed Brown Output Parameters: 1341b1a0a8a3SJed Brown + n - the number of subdomains for this processor (default value = 1) 1342b1a0a8a3SJed Brown . is - the index sets that define the subdomains for this processor 1343b1a0a8a3SJed Brown - is_local - the index sets that define the local part of the subdomains for this processor (can be PETSC_NULL) 1344b1a0a8a3SJed Brown 1345b1a0a8a3SJed Brown 1346b1a0a8a3SJed Brown Notes: 1347b1a0a8a3SJed Brown The IS numbering is in the parallel, global numbering of the vector. 1348b1a0a8a3SJed Brown 1349b1a0a8a3SJed Brown Level: advanced 1350b1a0a8a3SJed Brown 1351f746d493SDmitry Karpeev .keywords: PC, GASM, set, local, subdomains, additive Schwarz 1352b1a0a8a3SJed Brown 1353f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetOverlap(), PCGASMGetSubKSP(), 1354f746d493SDmitry Karpeev PCGASMCreateSubdomains2D(), PCGASMSetLocalSubdomains(), PCGASMGetLocalSubmatrices() 1355b1a0a8a3SJed Brown @*/ 1356f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMGetLocalSubdomains(PC pc,PetscInt *n,IS *is[],IS *is_local[]) 1357b1a0a8a3SJed Brown { 1358f746d493SDmitry Karpeev PC_GASM *osm; 1359b1a0a8a3SJed Brown PetscErrorCode ierr; 1360b1a0a8a3SJed Brown PetscBool match; 1361b1a0a8a3SJed Brown 1362b1a0a8a3SJed Brown PetscFunctionBegin; 1363b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1364b1a0a8a3SJed Brown PetscValidIntPointer(n,2); 1365b1a0a8a3SJed Brown if (is) PetscValidPointer(is,3); 1366f746d493SDmitry Karpeev ierr = PetscTypeCompare((PetscObject)pc,PCGASM,&match);CHKERRQ(ierr); 1367b1a0a8a3SJed Brown if (!match) { 1368b1a0a8a3SJed Brown if (n) *n = 0; 1369b1a0a8a3SJed Brown if (is) *is = PETSC_NULL; 1370b1a0a8a3SJed Brown } else { 1371f746d493SDmitry Karpeev osm = (PC_GASM*)pc->data; 1372ab3e923fSDmitry Karpeev if (n) *n = osm->n; 1373b1a0a8a3SJed Brown if (is) *is = osm->is; 1374b1a0a8a3SJed Brown if (is_local) *is_local = osm->is_local; 1375b1a0a8a3SJed Brown } 1376b1a0a8a3SJed Brown PetscFunctionReturn(0); 1377b1a0a8a3SJed Brown } 1378b1a0a8a3SJed Brown 1379b1a0a8a3SJed Brown #undef __FUNCT__ 1380f746d493SDmitry Karpeev #define __FUNCT__ "PCGASMGetLocalSubmatrices" 1381b1a0a8a3SJed Brown /*@C 1382f746d493SDmitry Karpeev PCGASMGetLocalSubmatrices - Gets the local submatrices (for this processor 1383b1a0a8a3SJed Brown only) for the additive Schwarz preconditioner. 1384b1a0a8a3SJed Brown 1385b1a0a8a3SJed Brown Not Collective 1386b1a0a8a3SJed Brown 1387b1a0a8a3SJed Brown Input Parameter: 1388b1a0a8a3SJed Brown . pc - the preconditioner context 1389b1a0a8a3SJed Brown 1390b1a0a8a3SJed Brown Output Parameters: 1391b1a0a8a3SJed Brown + n - the number of matrices for this processor (default value = 1) 1392b1a0a8a3SJed Brown - mat - the matrices 1393b1a0a8a3SJed Brown 1394b1a0a8a3SJed Brown 1395b1a0a8a3SJed Brown Level: advanced 1396b1a0a8a3SJed Brown 1397f746d493SDmitry Karpeev .keywords: PC, GASM, set, local, subdomains, additive Schwarz, block Jacobi 1398b1a0a8a3SJed Brown 1399f746d493SDmitry Karpeev .seealso: PCGASMSetTotalSubdomains(), PCGASMSetOverlap(), PCGASMGetSubKSP(), 1400f746d493SDmitry Karpeev PCGASMCreateSubdomains2D(), PCGASMSetLocalSubdomains(), PCGASMGetLocalSubdomains() 1401b1a0a8a3SJed Brown @*/ 1402f746d493SDmitry Karpeev PetscErrorCode PETSCKSP_DLLEXPORT PCGASMGetLocalSubmatrices(PC pc,PetscInt *n,Mat *mat[]) 1403b1a0a8a3SJed Brown { 1404f746d493SDmitry Karpeev PC_GASM *osm; 1405b1a0a8a3SJed Brown PetscErrorCode ierr; 1406b1a0a8a3SJed Brown PetscBool match; 1407b1a0a8a3SJed Brown 1408b1a0a8a3SJed Brown PetscFunctionBegin; 1409b1a0a8a3SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1410b1a0a8a3SJed Brown PetscValidIntPointer(n,2); 1411b1a0a8a3SJed Brown if (mat) PetscValidPointer(mat,3); 1412b1a0a8a3SJed Brown if (!pc->setupcalled) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call after KSPSetUP() or PCSetUp()."); 1413f746d493SDmitry Karpeev ierr = PetscTypeCompare((PetscObject)pc,PCGASM,&match);CHKERRQ(ierr); 1414b1a0a8a3SJed Brown if (!match) { 1415b1a0a8a3SJed Brown if (n) *n = 0; 1416b1a0a8a3SJed Brown if (mat) *mat = PETSC_NULL; 1417b1a0a8a3SJed Brown } else { 1418f746d493SDmitry Karpeev osm = (PC_GASM*)pc->data; 1419ab3e923fSDmitry Karpeev if (n) *n = osm->n; 1420b1a0a8a3SJed Brown if (mat) *mat = osm->pmat; 1421b1a0a8a3SJed Brown } 1422b1a0a8a3SJed Brown PetscFunctionReturn(0); 1423b1a0a8a3SJed Brown } 1424