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