xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 21ef3d2006bc88660ff7570355a6b28d31c8399a)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4*21ef3d20SStefano Zampini #include <petscdm.h>
5674ae819SStefano Zampini #include <petscblaslapack.h>
6daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
7674ae819SStefano Zampini 
81e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
91e0482f5SStefano Zampini 
10f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
11f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
12f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
13a13144ffSStefano Zampini {
14a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
15a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
16a13144ffSStefano Zampini   PetscReal      *sing;
17a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
18a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
19a13144ffSStefano Zampini   PetscErrorCode ierr;
20a13144ffSStefano Zampini 
21a13144ffSStefano Zampini   PetscFunctionBegin;
22a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
23a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
24614dbb09SStefano Zampini #else
25a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
26a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
27a13144ffSStefano Zampini 
28a13144ffSStefano Zampini   /* workspace */
29a13144ffSStefano Zampini   if (!work) {
30a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
31f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
32a13144ffSStefano Zampini   } else {
33a13144ffSStefano Zampini     ulw   = lw;
34a13144ffSStefano Zampini     uwork = work;
35a13144ffSStefano Zampini   }
36a13144ffSStefano Zampini   n = PetscMin(nr,nc);
37a13144ffSStefano Zampini   if (!rwork) {
38a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
39a13144ffSStefano Zampini   } else {
40a13144ffSStefano Zampini     sing = rwork;
41a13144ffSStefano Zampini   }
42a13144ffSStefano Zampini 
43a13144ffSStefano Zampini   /* SVD */
44a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
45a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
46a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
47a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
51a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
52a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
53a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
54a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
55a13144ffSStefano Zampini   if (!rwork) {
56a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
57a13144ffSStefano Zampini   }
58a13144ffSStefano Zampini   if (!work) {
59a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   /* create B */
62f498cd09SStefano Zampini   if (!range) {
63a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
64a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
65a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
66f498cd09SStefano Zampini   } else {
67f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
68f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
69f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
70f498cd09SStefano Zampini   }
71a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
72a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
73614dbb09SStefano Zampini #endif
74614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
75a13144ffSStefano Zampini   PetscFunctionBegin;
76a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
77a13144ffSStefano Zampini #endif
78a13144ffSStefano Zampini   PetscFunctionReturn(0);
79a13144ffSStefano Zampini }
80a13144ffSStefano Zampini 
811e0482f5SStefano Zampini /* TODO REMOVE */
821e0482f5SStefano Zampini #if defined(PRINT_GDET)
831e0482f5SStefano Zampini static int inc = 0;
841e0482f5SStefano Zampini static int lev = 0;
851e0482f5SStefano Zampini #endif
861e0482f5SStefano Zampini 
871e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
88a13144ffSStefano Zampini {
89a13144ffSStefano Zampini   PetscErrorCode ierr;
90a13144ffSStefano Zampini   Mat            GE,GEd;
91a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
92a13144ffSStefano Zampini   PetscScalar    *ptr;
93a13144ffSStefano Zampini 
94a13144ffSStefano Zampini   PetscFunctionBegin;
95a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
96c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
97a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
98a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
99a13144ffSStefano Zampini 
100a13144ffSStefano Zampini   /* gradients */
101a13144ffSStefano Zampini   ptr  = work + 5*esize;
1027dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
103a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
104a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
105a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini 
107a13144ffSStefano Zampini   /* constants */
108a13144ffSStefano Zampini   ptr += rsize*csize;
109a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1107dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
111a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
112a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
113f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1151e0482f5SStefano Zampini 
1161e0482f5SStefano Zampini   if (corners) {
1171e0482f5SStefano Zampini     Mat            GEc;
1181e0482f5SStefano Zampini     PetscScalar    *vals,v;
1191e0482f5SStefano Zampini 
1207dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1211e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1221e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
123637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
124637e8532SStefano Zampini     v    = 1.;
1251e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1261e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1271e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1281e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1291e0482f5SStefano Zampini #if defined(PRINT_GDET)
1301e0482f5SStefano Zampini     {
1311e0482f5SStefano Zampini       PetscViewer viewer;
1321e0482f5SStefano Zampini       char filename[256];
1331e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1341e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1351e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1361e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1371e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini     }
1441e0482f5SStefano Zampini #endif
1451e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1471e0482f5SStefano Zampini   }
1481e0482f5SStefano Zampini 
149a13144ffSStefano Zampini   PetscFunctionReturn(0);
150a13144ffSStefano Zampini }
151a13144ffSStefano Zampini 
152a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
153a13144ffSStefano Zampini {
154a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
155a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1560569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
157eee23b56SStefano Zampini   Vec                    tvec;
158a13144ffSStefano Zampini   PetscSF                sfv;
1591e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
160a13144ffSStefano Zampini   MPI_Comm               comm;
161c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
162c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1637d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
164a13144ffSStefano Zampini   PetscScalar            *vals,*work;
165a13144ffSStefano Zampini   PetscReal              *rwork;
166a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1671e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
168a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
169eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
170b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
171a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
172b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
173637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
174b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
175b03ebc13SStefano Zampini   PetscInt               *emarks;
176b03ebc13SStefano Zampini #endif
177213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
178a13144ffSStefano Zampini   PetscErrorCode         ierr;
179a13144ffSStefano Zampini 
180a13144ffSStefano Zampini   PetscFunctionBegin;
181213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
182213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
183213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
184213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
185213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
186213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
187213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
188213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
189a13144ffSStefano Zampini   print      = PETSC_FALSE;
190213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
191a13144ffSStefano Zampini 
192213b8bfaSStefano Zampini   /* Command line customization */
193213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
194213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
195213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
196213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
197213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
200213b8bfaSStefano Zampini 
201213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2021e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2031e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
204213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
205213b8bfaSStefano Zampini   if (!singular) {
206a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
207a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
208c2151214SStefano Zampini     for (i=0;i<n;i++) {
209a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
210a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
211a13144ffSStefano Zampini         break;
212a13144ffSStefano Zampini       }
213a13144ffSStefano Zampini     }
214a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
215a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
216a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
217213b8bfaSStefano Zampini   }
218a13144ffSStefano Zampini 
219213b8bfaSStefano Zampini   /* Get Nedelec field */
220213b8bfaSStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
221c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= pcbddc->n_ISForDofsLocal) SETERRQ2(comm,PETSC_ERR_USER,"Invalid field for Nedelec %d: number of fields is %d",field,pcbddc->n_ISForDofsLocal);
222213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
223c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
224c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
225c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
226213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
227213b8bfaSStefano Zampini     ne            = n;
228213b8bfaSStefano Zampini     nedfieldlocal = NULL;
229213b8bfaSStefano Zampini     global        = PETSC_TRUE;
230213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
231213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
232213b8bfaSStefano Zampini 
233213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
234213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
235213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
236213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
237213b8bfaSStefano Zampini       PetscInt nc;
238213b8bfaSStefano Zampini 
239213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
240213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
241213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
242213b8bfaSStefano Zampini     }
243213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
244213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
245213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
246213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
247213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
248213b8bfaSStefano Zampini   } else {
249213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
250213b8bfaSStefano Zampini   }
251213b8bfaSStefano Zampini 
252213b8bfaSStefano Zampini   /* Sanity checks */
253213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
254213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
255213b8bfaSStefano Zampini   if (order && ne%order) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %d it's not a multiple of the order %d",ne,order);
256213b8bfaSStefano Zampini 
257213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2581e0482f5SStefano Zampini   if (setprimal) {
259eee23b56SStefano Zampini     IS       enedfieldlocal;
260eee23b56SStefano Zampini     PetscInt *eidxs;
261eee23b56SStefano Zampini 
262eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
263eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
264213b8bfaSStefano Zampini     if (nedfieldlocal) {
265213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
266eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
267eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
268eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
269eee23b56SStefano Zampini         }
270eee23b56SStefano Zampini       }
271eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
272213b8bfaSStefano Zampini     } else {
273213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
274213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
275213b8bfaSStefano Zampini           eidxs[cum++] = i;
276213b8bfaSStefano Zampini         }
277213b8bfaSStefano Zampini       }
278213b8bfaSStefano Zampini     }
279213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
280eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
281eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
282eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2831e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2851e0482f5SStefano Zampini     PetscFunctionReturn(0);
2861e0482f5SStefano Zampini   }
287a13144ffSStefano Zampini 
288213b8bfaSStefano Zampini   /* Compute some l2g maps */
289213b8bfaSStefano Zampini   if (nedfieldlocal) {
290c2151214SStefano Zampini     IS is;
291c2151214SStefano Zampini 
292c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
293c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2941e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2951e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2961e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
2981e0482f5SStefano Zampini     if (global) {
2991e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3001e0482f5SStefano Zampini       el2g = al2g;
3011e0482f5SStefano Zampini     } else {
3021e0482f5SStefano Zampini       IS gis;
3031e0482f5SStefano Zampini 
3041e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3051e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3061e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3071e0482f5SStefano Zampini     }
308c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
309c2151214SStefano Zampini   } else {
3101e0482f5SStefano Zampini     /* restore default */
3111e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3121e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3131e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3141e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3151e0482f5SStefano Zampini     el2g = al2g;
316c2151214SStefano Zampini     fl2g = NULL;
317c2151214SStefano Zampini   }
318a13144ffSStefano Zampini 
319213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
320c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
321c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
322c2151214SStefano Zampini   if (nedfieldlocal) {
323c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
324c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
325c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
326c2151214SStefano Zampini   } else {
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
328c2151214SStefano Zampini   }
329c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
330c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
331213b8bfaSStefano Zampini 
332213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
333213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
334213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3351e0482f5SStefano Zampini     if (global) {
3361e0482f5SStefano Zampini       PetscInt rst;
3371e0482f5SStefano Zampini 
338c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
339c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
340c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
341c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
342c2151214SStefano Zampini         }
343c2151214SStefano Zampini       }
344a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
345c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3461e0482f5SStefano Zampini     } else {
3471e0482f5SStefano Zampini       PetscInt *tbz;
3481e0482f5SStefano Zampini 
3491e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3501e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3511e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3521e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3541e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3551e0482f5SStefano Zampini           tbz[cum++] = i;
3561e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3571e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3581e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3591e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3601e0482f5SStefano Zampini     }
361213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
362213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
363213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
364213b8bfaSStefano Zampini   }
365a13144ffSStefano Zampini 
366a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
367a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
368a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3697dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
372a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
375a13144ffSStefano Zampini 
376213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
377c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
378a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
379a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
380a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
385213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
386213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
387a13144ffSStefano Zampini 
3881e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
389213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
390a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
391213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
392a13144ffSStefano Zampini 
393213b8bfaSStefano Zampini   if (print) {
394213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
395213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
396213b8bfaSStefano Zampini   }
397213b8bfaSStefano Zampini 
398213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
3990569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4000569b399SStefano Zampini 
401a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4024e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4034e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
404a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
405a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
406a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4077d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
408c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
409a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
410a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
411a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
412c2151214SStefano Zampini     IS is;
413c2151214SStefano Zampini 
414c2151214SStefano Zampini     if (fl2g) {
415c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
416c2151214SStefano Zampini     } else {
417c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
418c2151214SStefano Zampini     }
419c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
420c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
421a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
422a13144ffSStefano Zampini       if (idxs[i] >= 0) {
423a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4247d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
425a13144ffSStefano Zampini       }
426a13144ffSStefano Zampini     }
427c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
428c2151214SStefano Zampini     if (fl2g) {
429c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
430c2151214SStefano Zampini     }
431a13144ffSStefano Zampini   }
432a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
433c2151214SStefano Zampini     IS is;
434c2151214SStefano Zampini 
435c2151214SStefano Zampini     if (fl2g) {
436c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
437c2151214SStefano Zampini     } else {
438c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
439c2151214SStefano Zampini     }
440c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
441c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
442a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
443a13144ffSStefano Zampini       if (idxs[i] >= 0) {
444a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
445a13144ffSStefano Zampini       }
446a13144ffSStefano Zampini     }
447c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
448c2151214SStefano Zampini     if (fl2g) {
449c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
450a13144ffSStefano Zampini     }
451c2151214SStefano Zampini   }
452c2151214SStefano Zampini 
453213b8bfaSStefano Zampini   /* Count neighs per dof */
454637e8532SStefano Zampini   ierr = PetscCalloc1(ne,&ecount);CHKERRQ(ierr);
455637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&eneighs);CHKERRQ(ierr);
456637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
457637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
458637e8532SStefano Zampini     cum += n_shared[i];
459637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
460637e8532SStefano Zampini       ecount[shared[i][j]]++;
461637e8532SStefano Zampini     }
462637e8532SStefano Zampini   }
463637e8532SStefano Zampini   if (ne) {
464637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&eneighs[0]);CHKERRQ(ierr);
465637e8532SStefano Zampini   }
466637e8532SStefano Zampini   for (i=1;i<ne;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
467637e8532SStefano Zampini   ierr = PetscMemzero(ecount,ne*sizeof(PetscInt));CHKERRQ(ierr);
468637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
469637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
470637e8532SStefano Zampini       PetscInt k = shared[i][j];
471637e8532SStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
472637e8532SStefano Zampini       ecount[k]++;
473637e8532SStefano Zampini     }
474637e8532SStefano Zampini   }
475637e8532SStefano Zampini   for (i=0;i<ne;i++) {
476637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr);
477637e8532SStefano Zampini   }
478637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
479637e8532SStefano Zampini   ierr = PetscCalloc1(nv,&vcount);CHKERRQ(ierr);
480637e8532SStefano Zampini   ierr = PetscMalloc1(nv,&vneighs);CHKERRQ(ierr);
481637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
482637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
483637e8532SStefano Zampini     cum += n_shared[i];
484637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
485637e8532SStefano Zampini       vcount[shared[i][j]]++;
486637e8532SStefano Zampini     }
487637e8532SStefano Zampini   }
488637e8532SStefano Zampini   if (nv) {
489637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&vneighs[0]);CHKERRQ(ierr);
490637e8532SStefano Zampini   }
491637e8532SStefano Zampini   for (i=1;i<nv;i++) vneighs[i] = vneighs[i-1] + vcount[i-1];
492637e8532SStefano Zampini   ierr = PetscMemzero(vcount,nv*sizeof(PetscInt));CHKERRQ(ierr);
493637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
494637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
495637e8532SStefano Zampini       PetscInt k = shared[i][j];
496637e8532SStefano Zampini       vneighs[k][vcount[k]] = neigh[i];
497637e8532SStefano Zampini       vcount[k]++;
498637e8532SStefano Zampini     }
499637e8532SStefano Zampini   }
500637e8532SStefano Zampini   for (i=0;i<nv;i++) {
501637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&vcount[i],vneighs[i]);CHKERRQ(ierr);
502637e8532SStefano Zampini   }
503637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
504637e8532SStefano Zampini 
5057d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
5067d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
50762b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
50862b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
5097d871cd7SStefano Zampini     if ((ecount[i] > 1 && !PetscBTLookup(btbd,i)) || (ecount[i] == 1 && PetscBTLookup(btb,i))) {
51062b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini     }
51262b0c6f7SStefano Zampini   }
513637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
51462b0c6f7SStefano Zampini   if (!conforming) {
51562b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
51662b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
51762b0c6f7SStefano Zampini   }
5184e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
519dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
52062b0c6f7SStefano Zampini   cum  = 0;
521a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
522dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
52362b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
524a13144ffSStefano Zampini       marks[cum++] = i;
525dec27d64SStefano Zampini       continue;
526dec27d64SStefano Zampini     }
527dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
52862b0c6f7SStefano Zampini     if (!conforming) {
52962b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
530a13144ffSStefano Zampini         marks[cum++] = i;
531a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
532a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
533a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
534a13144ffSStefano Zampini         }
53562b0c6f7SStefano Zampini       } else {
53662b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
53762b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
53862b0c6f7SStefano Zampini            - at most 2 endpoints
53962b0c6f7SStefano Zampini            - order-1 interior nodal dofs
54062b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
54162b0c6f7SStefano Zampini         */
54262b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
54362b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
54462b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
54562b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
54662b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
54762b0c6f7SStefano Zampini           if (nconn > order) ends++;
54862b0c6f7SStefano Zampini           else if (nconn == order) ints++;
54962b0c6f7SStefano Zampini           else undef++;
55062b0c6f7SStefano Zampini         }
55162b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
55262b0c6f7SStefano Zampini           marks[cum++] = i;
55362b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
55462b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
55562b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
55662b0c6f7SStefano Zampini           }
55762b0c6f7SStefano Zampini         }
55862b0c6f7SStefano Zampini       }
559a13144ffSStefano Zampini     }
560dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
561dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
562dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
563dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
564a13144ffSStefano Zampini     }
565dec27d64SStefano Zampini   }
56662b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
567dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5684e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
56962b0c6f7SStefano Zampini   if (!conforming) {
57062b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
57162b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
57262b0c6f7SStefano Zampini   }
5734e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
574637e8532SStefano Zampini 
575b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5764e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
577a13144ffSStefano Zampini   if (print) {
5784e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5794e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5804e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
581a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
582a13144ffSStefano Zampini   }
583a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
584dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
585a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
586637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5877d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
588b03ebc13SStefano Zampini     if (!order) { /* variable order */
589dec27d64SStefano Zampini       PetscReal vorder = 0.;
590dec27d64SStefano Zampini 
591dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
592dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
593dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
594dec27d64SStefano Zampini       ord  = 1;
595dec27d64SStefano Zampini     }
596a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
597dec27d64SStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",test,i,ord);
598a13144ffSStefano Zampini #endif
599637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
6007d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
6017d871cd7SStefano Zampini         bdir = PETSC_TRUE;
6027d871cd7SStefano Zampini         break;
6037d871cd7SStefano Zampini       }
604637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
605637e8532SStefano Zampini         sneighs = PETSC_FALSE;
606637e8532SStefano Zampini       } else {
607637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
608637e8532SStefano Zampini         for (k=0;k<vc;k++) {
609637e8532SStefano Zampini           if (vn[k] != en[k]) {
610637e8532SStefano Zampini             sneighs = PETSC_FALSE;
611637e8532SStefano Zampini             break;
612637e8532SStefano Zampini           }
613637e8532SStefano Zampini         }
614637e8532SStefano Zampini       }
615637e8532SStefano Zampini     }
6167d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
6177d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
618a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
619dec27d64SStefano Zampini     } else if (test == ord) {
620b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
621a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
622a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
623a13144ffSStefano Zampini       } else {
624a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
625a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
626a13144ffSStefano Zampini       }
627a13144ffSStefano Zampini     }
628a13144ffSStefano Zampini   }
629637e8532SStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
630637e8532SStefano Zampini   ierr = PetscFree(vcount);CHKERRQ(ierr);
631637e8532SStefano Zampini   if (ne) {
632637e8532SStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
633637e8532SStefano Zampini   }
634637e8532SStefano Zampini   if (nv) {
635637e8532SStefano Zampini     ierr = PetscFree(vneighs[0]);CHKERRQ(ierr);
636637e8532SStefano Zampini   }
637637e8532SStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
638637e8532SStefano Zampini   ierr = PetscFree(vneighs);CHKERRQ(ierr);
6397d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
640b03ebc13SStefano Zampini 
641b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
642b03ebc13SStefano Zampini   if (order != 1) {
643b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
644b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
645b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
646b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
647b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
648b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
649b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
650b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
651b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
652b03ebc13SStefano Zampini             PetscInt v = jjt[k];
653b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
654b03ebc13SStefano Zampini               found = PETSC_TRUE;
655b03ebc13SStefano Zampini               break;
656b03ebc13SStefano Zampini             }
657b03ebc13SStefano Zampini           }
658b03ebc13SStefano Zampini         }
659b03ebc13SStefano Zampini         if (!found) {
660b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
661b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
662b03ebc13SStefano Zampini         } else {
663b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
664b03ebc13SStefano Zampini         }
665b03ebc13SStefano Zampini       }
666b03ebc13SStefano Zampini     }
667b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
668b03ebc13SStefano Zampini   }
669dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
670a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
671b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
672a13144ffSStefano Zampini 
673a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6740569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
675a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6764e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
677a13144ffSStefano Zampini 
6784e64d54eSstefano_zampini   /* Mark interior nodal dofs */
679a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6804e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
681a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
682a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6834e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
684a13144ffSStefano Zampini     }
685a13144ffSStefano Zampini   }
686a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
687a13144ffSStefano Zampini 
688a13144ffSStefano Zampini   /* communicate corners and splitpoints */
689a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
690a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
691a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
692a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
693a13144ffSStefano Zampini 
694a13144ffSStefano Zampini   if (print) {
695a13144ffSStefano Zampini     IS tbz;
696a13144ffSStefano Zampini 
697a13144ffSStefano Zampini     cum = 0;
698a13144ffSStefano Zampini     for (i=0;i<nv;i++)
699a13144ffSStefano Zampini       if (sfvleaves[i])
700a13144ffSStefano Zampini         vmarks[cum++] = i;
701a13144ffSStefano Zampini 
702a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
703a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
704a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
705a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
706a13144ffSStefano Zampini   }
707a13144ffSStefano Zampini 
708a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
709a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
710a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
711a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
712a13144ffSStefano Zampini 
7134e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
7144e64d54eSstefano_zampini      and interior nodal dofs */
715a13144ffSStefano Zampini   cum = 0;
716a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
717a13144ffSStefano Zampini     if (sfvleaves[i]) {
718a13144ffSStefano Zampini       vmarks[cum++] = i;
719a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
720a13144ffSStefano Zampini     }
7214e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
722a13144ffSStefano Zampini   }
7234e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
724a13144ffSStefano Zampini   if (print) {
725a13144ffSStefano Zampini     IS tbz;
726a13144ffSStefano Zampini 
727a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
7284e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
729a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
730a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
731a13144ffSStefano Zampini   }
732a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
733a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
734a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
735a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
736a13144ffSStefano Zampini 
737a13144ffSStefano Zampini   /* Recompute G */
738a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
739a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
740a13144ffSStefano Zampini   if (print) {
741a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
742a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
743a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
744a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
745a13144ffSStefano Zampini   }
746a13144ffSStefano Zampini 
747a13144ffSStefano Zampini   /* Get primal dofs (if any) */
748a13144ffSStefano Zampini   cum = 0;
749a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
750a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
751a13144ffSStefano Zampini   }
752c2151214SStefano Zampini   if (fl2g) {
753c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
754c2151214SStefano Zampini   }
755a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
756a13144ffSStefano Zampini   if (print) {
757a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
758a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
759a13144ffSStefano Zampini   }
760a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
761c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
762a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
763a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
764a13144ffSStefano Zampini 
765a13144ffSStefano Zampini   /* Compute edge connectivity */
766a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
767a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
768a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
769c2151214SStefano Zampini   if (fl2g) {
770c2151214SStefano Zampini     PetscBT   btf;
771c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
772c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
773c2151214SStefano Zampini 
774c2151214SStefano Zampini     /* create CSR for all local dofs */
775c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
776c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
777c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %d. Should be %d\n",pcbddc->mat_graph->nvtxs_csr,n);
778c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
779c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
780c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
781c2151214SStefano Zampini       rest = PETSC_TRUE;
782c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
783c2151214SStefano Zampini     } else {
784c2151214SStefano Zampini       free   = PETSC_TRUE;
785c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
786c2151214SStefano Zampini       iiu[0] = 0;
787c2151214SStefano Zampini       for (i=0;i<n;i++) {
788c2151214SStefano Zampini         iiu[i+1] = i+1;
789c2151214SStefano Zampini         jju[i]   = -1;
790d904f53bSStefano Zampini       }
791c2151214SStefano Zampini     }
792c2151214SStefano Zampini 
793c2151214SStefano Zampini     /* import sizes of CSR */
794c2151214SStefano Zampini     iia[0] = 0;
795c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
796c2151214SStefano Zampini 
797c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
798c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
799c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
800c2151214SStefano Zampini     for (i=0;i<ne;i++) {
801c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
802c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
803c2151214SStefano Zampini     }
804c2151214SStefano Zampini 
805c2151214SStefano Zampini     /* iia in CSR */
806c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
807c2151214SStefano Zampini 
808c2151214SStefano Zampini     /* jja in CSR */
809c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
810c2151214SStefano Zampini     for (i=0;i<n;i++)
811c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
812c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
813c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
814c2151214SStefano Zampini 
815c2151214SStefano Zampini     /* map edge dofs connectivity */
8161e0482f5SStefano Zampini     if (jj) {
817c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
818c2151214SStefano Zampini       for (i=0;i<ne;i++) {
819c2151214SStefano Zampini         PetscInt e = idxs[i];
820c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
821c2151214SStefano Zampini       }
8221e0482f5SStefano Zampini     }
823c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
824c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
825c2151214SStefano Zampini     if (rest) {
826c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
827c2151214SStefano Zampini     }
828c2151214SStefano Zampini     if (free) {
829c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
830c2151214SStefano Zampini     }
831c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
832c2151214SStefano Zampini   } else {
833c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
834c2151214SStefano Zampini   }
835c2151214SStefano Zampini 
836a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
837a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
838213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
839a13144ffSStefano Zampini 
840a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
841c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
842a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
843a13144ffSStefano Zampini 
844c2151214SStefano Zampini   if (fl2g) {
845c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
846c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
847c2151214SStefano Zampini     for (i=0;i<nee;i++) {
848c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
849c2151214SStefano Zampini     }
850c2151214SStefano Zampini   } else {
851c2151214SStefano Zampini     eedges  = alleedges;
852c2151214SStefano Zampini     primals = allprimals;
853c2151214SStefano Zampini   }
854c2151214SStefano Zampini 
855a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
856a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
857c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
858c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
859c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
860c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
861c2151214SStefano Zampini   if (print) {
862c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
863c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
864c2151214SStefano Zampini   }
865c2151214SStefano Zampini 
866c2151214SStefano Zampini   maxsize = 0;
867a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
868a13144ffSStefano Zampini     PetscInt size,mark = i+1;
869a13144ffSStefano Zampini 
870a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
871a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
872a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
873a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
874a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
875a13144ffSStefano Zampini   }
876a13144ffSStefano Zampini 
877a13144ffSStefano Zampini   /* Find coarse edge endpoints */
878a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
879a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
880a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
881a13144ffSStefano Zampini     PetscInt mark = i+1,size;
882a13144ffSStefano Zampini 
883a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8841e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8851e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
886a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
887a13144ffSStefano Zampini     if (print) {
888a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
889a13144ffSStefano Zampini       ISView(eedges[i],NULL);
890a13144ffSStefano Zampini     }
891a13144ffSStefano Zampini     for (j=0;j<size;j++) {
892a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
893a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
894a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
895a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
896a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
897a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
898a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
899a13144ffSStefano Zampini           PetscInt  k2;
900a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
901a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
902c2151214SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %d: mark %d (ref mark %d), boundary %d\n",jjt[k2],marks[jjt[k2]],mark,!!PetscBTLookup(btb,jjt[k2]));
903c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
904c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
905c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
906a13144ffSStefano Zampini               corner = PETSC_TRUE;
907a13144ffSStefano Zampini               break;
908a13144ffSStefano Zampini             }
909a13144ffSStefano Zampini           }
910a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
911a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
912a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
913a13144ffSStefano Zampini           } else {
914a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
915a13144ffSStefano Zampini           }
916a13144ffSStefano Zampini         }
917a13144ffSStefano Zampini       }
918a13144ffSStefano Zampini     }
919a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
920a13144ffSStefano Zampini   }
921a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
922a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
923c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
924a13144ffSStefano Zampini 
925a13144ffSStefano Zampini   /* Reset marked primal dofs */
926a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
927a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
928a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
929a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
930a13144ffSStefano Zampini 
9310569b399SStefano Zampini   /* Now use the initial lG */
9320569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
9330569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
9340569b399SStefano Zampini   lG   = lGinit;
9350569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
9360569b399SStefano Zampini 
937a13144ffSStefano Zampini   /* Compute extended cols indices */
938b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
939b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
940a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
941a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
942a13144ffSStefano Zampini   i   *= maxsize;
943b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
945a13144ffSStefano Zampini   eerr = PETSC_FALSE;
946a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
947b03ebc13SStefano Zampini     PetscInt size,found = 0;
948a13144ffSStefano Zampini 
949a13144ffSStefano Zampini     cum  = 0;
950a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9511e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9521e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
953a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
954b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
955a13144ffSStefano Zampini     for (j=0;j<size;j++) {
956a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
957b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
958b03ebc13SStefano Zampini         PetscInt vv = jj[k];
959b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
960b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
961b03ebc13SStefano Zampini       }
962a13144ffSStefano Zampini     }
963a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
964a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
965a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
966a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
967a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
968a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
969a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
970b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
971b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
972a13144ffSStefano Zampini       if (print) {
973a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
974a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
975a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
976a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
977a13144ffSStefano Zampini       }
978a13144ffSStefano Zampini       eerr = PETSC_TRUE;
979a13144ffSStefano Zampini     }
980a13144ffSStefano Zampini   }
9814e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
982a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
983a13144ffSStefano Zampini   if (done) {
984a13144ffSStefano Zampini     PetscInt *newprimals;
985a13144ffSStefano Zampini 
986a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
987a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
988a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
989a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
990a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9910569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
992b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
993a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
994b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
995b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
996a13144ffSStefano Zampini         PetscInt size,mark = i+1;
997a13144ffSStefano Zampini 
998a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
999a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1000c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
1001a13144ffSStefano Zampini         for (j=0;j<size;j++) {
1002a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
1003b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
1004a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1005a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
1006a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
1007a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
1008b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
1009b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
1010a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
1011a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
1012a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
1013a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
1014a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
1015b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
1016a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
1017a13144ffSStefano Zampini                   /* finally set the new corners */
1018a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
1019b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
1020a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
1021a13144ffSStefano Zampini                   }
1022a13144ffSStefano Zampini                 }
1023a13144ffSStefano Zampini               }
1024b03ebc13SStefano Zampini             } else {
1025b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
1026a13144ffSStefano Zampini             }
1027a13144ffSStefano Zampini           }
1028a13144ffSStefano Zampini         }
1029b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
1030b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
1031b03ebc13SStefano Zampini 
1032b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
1033b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
1034b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1035b03ebc13SStefano Zampini             PetscInt k2;
1036b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
1037b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
1038b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
1039b03ebc13SStefano Zampini           }
1040b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
1041b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
1042b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
1043b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
1044b03ebc13SStefano Zampini             }
1045b03ebc13SStefano Zampini           }
1046b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
1047b03ebc13SStefano Zampini         }
1048a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1049a13144ffSStefano Zampini       }
1050a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1051a13144ffSStefano Zampini     }
1052b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10530569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1054a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1055c2151214SStefano Zampini     if (fl2g) {
1056c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1057c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1058c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1059c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1060c2151214SStefano Zampini       }
1061c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1062c2151214SStefano Zampini     }
1063c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1064a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1065a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1066a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1067a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1068a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1069213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1070c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1071c2151214SStefano Zampini     if (fl2g) {
1072c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1073c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1074c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1075c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1076c2151214SStefano Zampini       }
1077c2151214SStefano Zampini     } else {
1078c2151214SStefano Zampini       eedges  = alleedges;
1079c2151214SStefano Zampini       primals = allprimals;
1080c2151214SStefano Zampini     }
1081b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1082a13144ffSStefano Zampini 
1083a13144ffSStefano Zampini     /* Mark again */
1084a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1085a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1086a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1087a13144ffSStefano Zampini 
1088a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1089a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1090a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1091a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1092a13144ffSStefano Zampini     }
1093a13144ffSStefano Zampini     if (print) {
1094a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1095a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1096a13144ffSStefano Zampini     }
1097a13144ffSStefano Zampini 
1098a13144ffSStefano Zampini     /* Recompute extended cols */
1099a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1100a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1101a13144ffSStefano Zampini       PetscInt size;
1102a13144ffSStefano Zampini 
1103a13144ffSStefano Zampini       cum  = 0;
1104a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11051e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
11061e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1107a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1108a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1109a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
11101e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1111a13144ffSStefano Zampini       }
1112a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1113a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1114a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1115a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1116a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1117a13144ffSStefano Zampini       if (cum != size -1) {
1118a13144ffSStefano Zampini         if (print) {
1119a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1120a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1121a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1122a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1123a13144ffSStefano Zampini         }
1124a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1125a13144ffSStefano Zampini       }
1126a13144ffSStefano Zampini     }
1127a13144ffSStefano Zampini   }
1128a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1129a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1130b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
11317d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1132a13144ffSStefano Zampini   /* an error should not occur at this point */
1133a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1134a13144ffSStefano Zampini 
11354e64d54eSstefano_zampini   /* Check the number of endpoints */
11360569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1137b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1138b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
11394e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1140b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
11414e64d54eSstefano_zampini 
1142b03ebc13SStefano Zampini     /* init with defaults */
1143b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
11444e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11451e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
11461e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
11474e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1148b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11494e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11504e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11514e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11524e64d54eSstefano_zampini         PetscInt vv = jj[k];
11534e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1154b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1155b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11564e64d54eSstefano_zampini         }
11574e64d54eSstefano_zampini       }
11584e64d54eSstefano_zampini     }
1159b03ebc13SStefano Zampini     if (found != 2) {
1160b03ebc13SStefano Zampini       PetscInt e;
1161b03ebc13SStefano Zampini       if (fl2g) {
1162b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1163b03ebc13SStefano Zampini       } else {
1164b03ebc13SStefano Zampini         e = idxs[0];
1165b03ebc13SStefano Zampini       }
1166b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1167b03ebc13SStefano Zampini     }
1168eee23b56SStefano Zampini 
1169eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1170b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1171b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1172b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1173b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1174b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1175b03ebc13SStefano Zampini     }
1176eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11774e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1178b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %d: ce %d, corners (%d,%d)\n",i,cedges[i],corners[2*i],corners[2*i+1]);
11794e64d54eSstefano_zampini   }
11800569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11814e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11824e64d54eSstefano_zampini 
1183a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1184a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1185a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1186a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1187a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1188a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1189a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1190a13144ffSStefano Zampini 
1191a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1192a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1193a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1194a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1195a13144ffSStefano Zampini       if (emax < emarks[j]) {
1196a13144ffSStefano Zampini         emax = emarks[j];
1197a13144ffSStefano Zampini         eemax = j;
1198a13144ffSStefano Zampini       }
1199a13144ffSStefano Zampini     }
1200a13144ffSStefano Zampini     /* not relevant for edges */
1201a13144ffSStefano Zampini     if (!eemax) continue;
1202a13144ffSStefano Zampini 
1203a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1204a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1205c2151214SStefano Zampini         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %d and %d) connected through the %d nodal dof at edge dof %d\n",marks[jj[j]]-1,eemax,i,jj[j]);
1206a13144ffSStefano Zampini       }
1207a13144ffSStefano Zampini     }
1208a13144ffSStefano Zampini   }
1209a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1210a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1211a13144ffSStefano Zampini #endif
1212a13144ffSStefano Zampini 
1213a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1214a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1215a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1216a13144ffSStefano Zampini   extmem *= maxsize;
1217a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1220a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1221a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1222213b8bfaSStefano Zampini 
1223a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1224a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1225a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1226a13144ffSStefano Zampini         mark = marks[jj[j]];
1227a13144ffSStefano Zampini 
1228a13144ffSStefano Zampini     /* not relevant */
1229a13144ffSStefano Zampini     if (!mark) continue;
1230a13144ffSStefano Zampini 
1231a13144ffSStefano Zampini     /* import extended row */
1232a13144ffSStefano Zampini     mark--;
1233a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1234a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1235a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1236a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1237a13144ffSStefano Zampini     extrowcum[mark] += size;
1238a13144ffSStefano Zampini   }
1239a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1240213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1241213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1242213b8bfaSStefano Zampini 
1243213b8bfaSStefano Zampini   /* Compress extrows */
1244a13144ffSStefano Zampini   cum  = 0;
1245a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1246a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1247a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1248a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1249a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1250a13144ffSStefano Zampini   }
1251a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1252a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1253a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1254a13144ffSStefano Zampini 
1255a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1256a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1257a13144ffSStefano Zampini 
1258a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1259a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1260c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1261c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1262a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1263a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1264a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12651e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1266a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1267a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1268213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1269a13144ffSStefano Zampini 
1270a13144ffSStefano Zampini   /* Defaults to identity */
1271c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1272a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1273a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1274a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1275a13144ffSStefano Zampini 
12761e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12771e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12781e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12791e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12801e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12811e0482f5SStefano Zampini     IS                     wis,gwis;
12821e0482f5SStefano Zampini     PetscInt               cnv,cne;
12831e0482f5SStefano Zampini 
12841e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12851e0482f5SStefano Zampini     if (fl2g) {
12861e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12871e0482f5SStefano Zampini     } else {
12881e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12891e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12901e0482f5SStefano Zampini     }
12911e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12921e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12931e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12941e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12951e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12961e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12971e0482f5SStefano Zampini 
12981e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12991e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
13001e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13011e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
13021e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
13031e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13041e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13051e0482f5SStefano Zampini 
13061e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
13071e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
13081e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
13091e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
13101e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
13111e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
13121e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
13141e0482f5SStefano Zampini   }
1315213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
13161e0482f5SStefano Zampini 
13171e0482f5SStefano Zampini #if defined(PRINT_GDET)
13181e0482f5SStefano Zampini   inc = 0;
13191e0482f5SStefano Zampini   lev = pcbddc->current_level;
13201e0482f5SStefano Zampini #endif
1321213b8bfaSStefano Zampini 
1322213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1323a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1324a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
13251e0482f5SStefano Zampini     IS          cornersis = NULL;
13261e0482f5SStefano Zampini     PetscScalar cvals[2];
1327a13144ffSStefano Zampini 
13281e0482f5SStefano Zampini     if (pcbddc->nedcG) {
13291e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
13301e0482f5SStefano Zampini     }
13311e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1332a13144ffSStefano Zampini     if (Gins && GKins) {
1333a13144ffSStefano Zampini       PetscScalar    *data;
1334a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1335a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1336a13144ffSStefano Zampini 
1337a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1338a13144ffSStefano Zampini       /* H1 */
1339a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1340a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1341a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1342a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1343a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1344a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1345a13144ffSStefano Zampini       /* complement */
1346a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
13471e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1348213b8bfaSStefano Zampini       if (ncc + nch != nrc) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %d and Gins %d does not match %d for coarse edge %d",ncc,nch,nrc,i);
1349213b8bfaSStefano Zampini       if (ncc != 1 && pcbddc->nedcG) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the coarse discrete gradient for coarse edge %d with ncc %d",i,ncc);
1350a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1351a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1352a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13531e0482f5SStefano Zampini 
13541e0482f5SStefano Zampini       /* coarse discrete gradient */
13551e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13561e0482f5SStefano Zampini         PetscInt cols[2];
13571e0482f5SStefano Zampini 
13581e0482f5SStefano Zampini         cols[0] = 2*i;
13591e0482f5SStefano Zampini         cols[1] = 2*i+1;
13601e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13611e0482f5SStefano Zampini       }
1362a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1363a13144ffSStefano Zampini     }
1364a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1365a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13661e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1367a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1368a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1369a13144ffSStefano Zampini   }
1370213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1371a13144ffSStefano Zampini 
1372a13144ffSStefano Zampini   /* Start assembling */
1373a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13741e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13751e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13761e0482f5SStefano Zampini   }
1377a13144ffSStefano Zampini 
1378a13144ffSStefano Zampini   /* Free */
1379c2151214SStefano Zampini   if (fl2g) {
1380c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1381c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1382c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1383c2151214SStefano Zampini     }
1384c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1385c2151214SStefano Zampini   }
1386eee23b56SStefano Zampini 
1387eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1388eee23b56SStefano Zampini   {
1389eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1390eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1391eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1392eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1393eee23b56SStefano Zampini 
1394eee23b56SStefano Zampini     /* find first primal edge */
1395eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1396eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1397eee23b56SStefano Zampini     } else {
1398eee23b56SStefano Zampini       if (fl2g) {
1399eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1400eee23b56SStefano Zampini       }
1401eee23b56SStefano Zampini       idxs = cedges;
1402eee23b56SStefano Zampini     }
1403eee23b56SStefano Zampini     cum = 0;
1404eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1405eee23b56SStefano Zampini 
1406eee23b56SStefano Zampini     /* adapt connected components */
1407eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1408eee23b56SStefano Zampini     graph->cptr[0] = 0;
1409eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1410eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1411eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1412eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1413eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1414eee23b56SStefano Zampini         ncc++;
1415eee23b56SStefano Zampini         lc--;
1416eee23b56SStefano Zampini         cum++;
1417eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1418eee23b56SStefano Zampini       }
1419eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1420eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1421eee23b56SStefano Zampini       ncc++;
1422eee23b56SStefano Zampini     }
1423eee23b56SStefano Zampini     graph->ncc = ncc;
1424eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1425eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1426eee23b56SStefano Zampini     }
1427eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1428eee23b56SStefano Zampini   }
1429213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1430c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1431c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1432213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1433eee23b56SStefano Zampini 
1434c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1435a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1436a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1437b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1438b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1439a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1440a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1441a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1442a13144ffSStefano Zampini 
1443a13144ffSStefano Zampini   /* Complete assembling */
1444a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14451e0482f5SStefano Zampini   if (pcbddc->nedcG) {
14461e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14471e0482f5SStefano Zampini #if 0
14481e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14491e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14501e0482f5SStefano Zampini #endif
14511e0482f5SStefano Zampini   }
1452a13144ffSStefano Zampini 
1453a13144ffSStefano Zampini   /* set change of basis */
1454213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1455a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1456a13144ffSStefano Zampini 
1457a13144ffSStefano Zampini   PetscFunctionReturn(0);
1458a13144ffSStefano Zampini }
1459a13144ffSStefano Zampini 
1460d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1461d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1462d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1463d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1464d8203eabSStefano Zampini {
1465d8203eabSStefano Zampini   PetscErrorCode ierr;
1466d8203eabSStefano Zampini   PetscInt       i;
1467d8203eabSStefano Zampini 
1468d8203eabSStefano Zampini   PetscFunctionBegin;
1469d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1470d8203eabSStefano Zampini     PetscInt first,last;
1471d8203eabSStefano Zampini 
1472d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
147386fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1474d8203eabSStefano Zampini     if (i>=first && i < last) {
1475d8203eabSStefano Zampini       PetscScalar *data;
1476d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1477d8203eabSStefano Zampini       if (!has_const) {
1478d8203eabSStefano Zampini         data[i-first] = 1.;
1479d8203eabSStefano Zampini       } else {
148086fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
148186fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1482d8203eabSStefano Zampini       }
1483d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1484d8203eabSStefano Zampini     }
1485d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1486d8203eabSStefano Zampini   }
1487d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1488d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1489d8203eabSStefano Zampini     PetscInt first,last;
1490ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1491d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1492d8203eabSStefano Zampini     if (i>=first && i < last) {
1493d8203eabSStefano Zampini       PetscScalar *data;
1494d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1495d8203eabSStefano Zampini       if (!has_const) {
1496d8203eabSStefano Zampini         data[i-first] = 0.;
1497d8203eabSStefano Zampini       } else {
149886fa73c5SStefano Zampini         data[2*i-first] = 0.;
149986fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1500d8203eabSStefano Zampini       }
1501d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1502d8203eabSStefano Zampini     }
1503d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1504ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1505d8203eabSStefano Zampini   }
1506d8203eabSStefano Zampini   PetscFunctionReturn(0);
1507d8203eabSStefano Zampini }
1508d8203eabSStefano Zampini 
15098ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1510669cc0f4SStefano Zampini {
1511a198735bSStefano Zampini   Mat                    loc_divudotp;
1512fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
15138ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1514669cc0f4SStefano Zampini   IS                     *faces,*edges;
1515669cc0f4SStefano Zampini   PetscScalar            *vals;
1516669cc0f4SStefano Zampini   const PetscScalar      *array;
1517669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
15181ae86dd6SStefano Zampini   PetscMPIInt            rank;
1519a198735bSStefano Zampini   PetscErrorCode         ierr;
1520669cc0f4SStefano Zampini 
1521669cc0f4SStefano Zampini   PetscFunctionBegin;
1522669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1523669cc0f4SStefano Zampini   if (graph->twodim) {
1524669cc0f4SStefano Zampini     lmaxneighs = 2;
1525669cc0f4SStefano Zampini   } else {
1526669cc0f4SStefano Zampini     lmaxneighs = 1;
1527669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1528669cc0f4SStefano Zampini       const PetscInt *idxs;
1529669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1530669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1531669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1532669cc0f4SStefano Zampini     }
1533669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1534669cc0f4SStefano Zampini   }
1535669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1536669cc0f4SStefano Zampini   maxsize = 0;
1537669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1538669cc0f4SStefano Zampini     PetscInt nn;
1539669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1540669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1541669cc0f4SStefano Zampini   }
1542669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1543669cc0f4SStefano Zampini     PetscInt nn;
1544669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1545669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1546669cc0f4SStefano Zampini   }
1547669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1548669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1549669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
15508ae0ca82SStefano Zampini   if (!transpose) {
15518ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
15528ae0ca82SStefano Zampini   } else {
15538ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
15548ae0ca82SStefano Zampini   }
1555669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
15561ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1557d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1558669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1559ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
15608ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1561669cc0f4SStefano Zampini   }
1562d8203eabSStefano Zampini 
1563669cc0f4SStefano Zampini   /* compute local quad vec */
1564a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15658ae0ca82SStefano Zampini   if (!transpose) {
1566a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15678ae0ca82SStefano Zampini   } else {
15688ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15698ae0ca82SStefano Zampini   }
1570669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15718ae0ca82SStefano Zampini   if (!transpose) {
1572a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15738ae0ca82SStefano Zampini   } else {
15748ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15758ae0ca82SStefano Zampini   }
1576fa23a32eSStefano Zampini   if (vl2l) {
1577fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1578fa23a32eSStefano Zampini   } else {
1579fa23a32eSStefano Zampini     vins = v;
1580fa23a32eSStefano Zampini   }
1581fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1582669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15839a962809SStefano Zampini 
15841ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15851ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1586669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1587669cc0f4SStefano Zampini     const PetscInt    *idxs;
1588669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1589669cc0f4SStefano Zampini 
1590669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1591669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1592669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15931ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1594669cc0f4SStefano Zampini     idx = -(idx+1);
1595669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1596669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1597669cc0f4SStefano Zampini   }
1598669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1599669cc0f4SStefano Zampini     const PetscInt    *idxs;
1600669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1601669cc0f4SStefano Zampini 
1602669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1603669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1604669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
16051ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1606669cc0f4SStefano Zampini     idx  = -(idx+1);
1607669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1608669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1609669cc0f4SStefano Zampini   }
1610c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1611fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1612fa23a32eSStefano Zampini   if (vl2l) {
1613fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1614fa23a32eSStefano Zampini   }
1615669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1616669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1617669cc0f4SStefano Zampini 
1618669cc0f4SStefano Zampini   /* assemble near null space */
1619669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1620669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1621669cc0f4SStefano Zampini   }
1622669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1623669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1624ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1625669cc0f4SStefano Zampini   }
1626669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1627669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1628669cc0f4SStefano Zampini }
1629669cc0f4SStefano Zampini 
1630669cc0f4SStefano Zampini 
16311f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
16321f4df5f7SStefano Zampini {
16331f4df5f7SStefano Zampini   PetscErrorCode ierr;
16341f4df5f7SStefano Zampini   Vec            local,global;
16351f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16361f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1637ef24a9ddSStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
16381f4df5f7SStefano Zampini 
16391f4df5f7SStefano Zampini   PetscFunctionBegin;
16401f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
1641*21ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16421f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16431f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16441f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16451f4df5f7SStefano Zampini       PetscInt i;
16461f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16471f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16481f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16491f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16501f4df5f7SStefano Zampini       }
16511f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16521f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16531f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16541f4df5f7SStefano Zampini     }
16551f4df5f7SStefano Zampini   } else {
1656*21ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
1657*21ef3d20SStefano Zampini       DM       dm;
1658*21ef3d20SStefano Zampini 
1659*21ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
1660*21ef3d20SStefano Zampini       if (!dm) {
1661*21ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
1662*21ef3d20SStefano Zampini       }
1663*21ef3d20SStefano Zampini       if (dm) {
1664*21ef3d20SStefano Zampini         IS      *fields;
1665*21ef3d20SStefano Zampini         PetscInt nf,i;
1666*21ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
1667*21ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1668*21ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
1669*21ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
1670*21ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
1671*21ef3d20SStefano Zampini         }
1672*21ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
1673*21ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
1674*21ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
1675*21ef3d20SStefano Zampini         PetscContainer   c;
1676*21ef3d20SStefano Zampini 
1677*21ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
1678*21ef3d20SStefano Zampini         if (c) {
1679*21ef3d20SStefano Zampini           MatISLocalFields lf;
1680*21ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
1681*21ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
1682*21ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16831f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1684986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1685*21ef3d20SStefano Zampini           if (i > 1) {
1686986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16871f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16881f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16891f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16901f4df5f7SStefano Zampini             }
16911f4df5f7SStefano Zampini           }
1692*21ef3d20SStefano Zampini         }
1693*21ef3d20SStefano Zampini       }
16947a0e7b2cSstefano_zampini     } else {
16957a0e7b2cSstefano_zampini       PetscInt i;
16967a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16977a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16987a0e7b2cSstefano_zampini       }
16991f4df5f7SStefano Zampini     }
1700986cdee1SStefano Zampini   }
17011f4df5f7SStefano Zampini 
17021f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
17031f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17047a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
17057a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17061f4df5f7SStefano Zampini   }
17071f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
17081f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17097a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
17107a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17111f4df5f7SStefano Zampini   }
17121f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
17131f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
17141f4df5f7SStefano Zampini   }
17151f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
17161f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
17177a0e7b2cSstefano_zampini 
17187a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
17197a0e7b2cSstefano_zampini }
17207a0e7b2cSstefano_zampini 
17217a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
17227a0e7b2cSstefano_zampini {
17237a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
17247a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
17257a0e7b2cSstefano_zampini   IS              nis;
17267a0e7b2cSstefano_zampini   const PetscInt  *idxs;
17277a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
17287a0e7b2cSstefano_zampini   PetscBool       *ld;
17297a0e7b2cSstefano_zampini 
17307a0e7b2cSstefano_zampini   PetscFunctionBegin;
17317a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
17327a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
17337a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
17347a0e7b2cSstefano_zampini     /* init rootdata with true */
17357a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
17367a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
17377a0e7b2cSstefano_zampini   } else {
17387a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
17397a0e7b2cSstefano_zampini   }
17407a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
17417a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
17427a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
17437a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
17447a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
17457a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
17467a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
17477a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
17487a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
17497a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
17507a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17517a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17527a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
17537a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
17547a0e7b2cSstefano_zampini   } else {
17557a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
17567a0e7b2cSstefano_zampini   }
17577a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
17587a0e7b2cSstefano_zampini     if (ld[i])
17597a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
17607a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
17617a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
17627a0e7b2cSstefano_zampini   *is  = nis;
17631f4df5f7SStefano Zampini   PetscFunctionReturn(0);
17641f4df5f7SStefano Zampini }
17651f4df5f7SStefano Zampini 
17663e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
17673e589ea0SStefano Zampini {
17683e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
17693e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
17703e589ea0SStefano Zampini   PetscErrorCode    ierr;
17713e589ea0SStefano Zampini 
17723e589ea0SStefano Zampini   PetscFunctionBegin;
17733e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
17743e589ea0SStefano Zampini     PetscFunctionReturn(0);
17753e589ea0SStefano Zampini   }
17763e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17773e589ea0SStefano Zampini     Vec swap;
17783e589ea0SStefano Zampini 
17793e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
17803e589ea0SStefano Zampini     swap = pcbddc->work_change;
17813e589ea0SStefano Zampini     pcbddc->work_change = r;
17823e589ea0SStefano Zampini     r = swap;
17833e589ea0SStefano Zampini   }
17843e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17853e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17863e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
17873e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
17883e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17893e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17903e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1791f913dca9SStefano Zampini     pcbddc->work_change = r;
17923e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
17933e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
17943e589ea0SStefano Zampini   }
17953e589ea0SStefano Zampini   PetscFunctionReturn(0);
17963e589ea0SStefano Zampini }
17973e589ea0SStefano Zampini 
1798a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1799a3df083aSStefano Zampini {
1800a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1801a3df083aSStefano Zampini   PetscErrorCode          ierr;
1802a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1803a3df083aSStefano Zampini 
1804a3df083aSStefano Zampini   PetscFunctionBegin;
1805a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1806a3df083aSStefano Zampini   if (transpose) {
1807a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1808a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1809a3df083aSStefano Zampini   } else {
1810a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1811a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1812a3df083aSStefano Zampini   }
1813a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1814a3df083aSStefano Zampini   if (apply_right) {
1815a3df083aSStefano Zampini     const PetscScalar *ax;
1816a3df083aSStefano Zampini     PetscInt          nl,i;
1817a3df083aSStefano Zampini 
1818a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1819a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1820a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1821a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1822a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1823a3df083aSStefano Zampini       PetscScalar    sum,val;
1824a3df083aSStefano Zampini       const PetscInt *idxs;
1825a3df083aSStefano Zampini       PetscInt       nz,j;
1826a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1827a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1828a3df083aSStefano Zampini       sum = 0.;
1829a3df083aSStefano Zampini       if (ctx->apply_p0) {
1830a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1831a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1832a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1833a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1834a3df083aSStefano Zampini         }
1835a3df083aSStefano Zampini       } else {
1836a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1837a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1838a3df083aSStefano Zampini         }
1839a3df083aSStefano Zampini       }
1840a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1841a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1842a3df083aSStefano Zampini     }
1843a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1844a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1845a3df083aSStefano Zampini   }
1846a3df083aSStefano Zampini   if (transpose) {
1847a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1848a3df083aSStefano Zampini   } else {
1849a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1850a3df083aSStefano Zampini   }
1851a3df083aSStefano Zampini   if (reset_x) {
1852a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1853a3df083aSStefano Zampini   }
1854a3df083aSStefano Zampini   if (apply_left) {
1855a3df083aSStefano Zampini     PetscScalar *ay;
1856a3df083aSStefano Zampini     PetscInt    i;
1857a3df083aSStefano Zampini 
1858a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1859a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1860a3df083aSStefano Zampini       PetscScalar    sum,val;
1861a3df083aSStefano Zampini       const PetscInt *idxs;
1862a3df083aSStefano Zampini       PetscInt       nz,j;
1863a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1864a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1865a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1866a3df083aSStefano Zampini       if (ctx->apply_p0) {
1867a3df083aSStefano Zampini         sum = 0.;
1868a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1869a3df083aSStefano Zampini           sum += ay[idxs[j]];
1870a3df083aSStefano Zampini           ay[idxs[j]] += val;
1871a3df083aSStefano Zampini         }
1872a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1873a3df083aSStefano Zampini       } else {
1874a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1875a3df083aSStefano Zampini           ay[idxs[j]] += val;
1876a3df083aSStefano Zampini         }
1877a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1878a3df083aSStefano Zampini       }
1879a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1880a3df083aSStefano Zampini     }
1881a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1882a3df083aSStefano Zampini   }
1883a3df083aSStefano Zampini   PetscFunctionReturn(0);
1884a3df083aSStefano Zampini }
1885a3df083aSStefano Zampini 
1886a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1887a3df083aSStefano Zampini {
1888a3df083aSStefano Zampini   PetscErrorCode ierr;
1889a3df083aSStefano Zampini 
1890a3df083aSStefano Zampini   PetscFunctionBegin;
1891a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1892a3df083aSStefano Zampini   PetscFunctionReturn(0);
1893a3df083aSStefano Zampini }
1894a3df083aSStefano Zampini 
1895a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1896a3df083aSStefano Zampini {
1897a3df083aSStefano Zampini   PetscErrorCode ierr;
1898a3df083aSStefano Zampini 
1899a3df083aSStefano Zampini   PetscFunctionBegin;
1900a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1901a3df083aSStefano Zampini   PetscFunctionReturn(0);
1902a3df083aSStefano Zampini }
1903a3df083aSStefano Zampini 
1904a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1905a3df083aSStefano Zampini {
1906a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1907a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1908a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1909a3df083aSStefano Zampini   PetscErrorCode          ierr;
1910a3df083aSStefano Zampini 
1911a3df083aSStefano Zampini   PetscFunctionBegin;
1912a3df083aSStefano Zampini   if (!restore) {
19131dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1914a3df083aSStefano Zampini     PetscScalar        *work;
1915b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1916a3df083aSStefano Zampini 
19179a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
19189a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1919a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1920a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1921a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1922a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1923a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1924a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1925a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1926a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1927a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1928a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1929a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1930a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1931059032f7SStefano Zampini     if (reuse) {
1932a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
19331dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1934059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1935059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1936059032f7SStefano Zampini       PetscInt               i;
1937059032f7SStefano Zampini 
1938059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1939059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1940059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1941059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1942059032f7SStefano Zampini       }
1943059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
19441dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1945059032f7SStefano Zampini     }
1946a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1947a3df083aSStefano Zampini     ctx->work = work;
1948a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1949a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1950a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1951a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1952a3df083aSStefano Zampini 
1953a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1954a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1955a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1956a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1957a3df083aSStefano Zampini   } else {
19581dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
19591dd7afcfSStefano Zampini       PetscFunctionReturn(0);
19601dd7afcfSStefano Zampini     }
1961a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1962a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1963a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
19641dd7afcfSStefano Zampini     ctx->A = NULL;
19651dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
19661dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
19671dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
19681dd7afcfSStefano Zampini     if (ctx->free) {
1969059032f7SStefano Zampini       PetscInt i;
19701dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1971059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1972059032f7SStefano Zampini       }
1973059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1974059032f7SStefano Zampini     }
1975a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1976a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1977a3df083aSStefano Zampini   }
1978a3df083aSStefano Zampini   PetscFunctionReturn(0);
1979a3df083aSStefano Zampini }
1980a3df083aSStefano Zampini 
1981a3df083aSStefano Zampini /* used just in bddc debug mode */
1982a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1983a3df083aSStefano Zampini {
1984a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1985a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1986a3df083aSStefano Zampini   Mat            An;
1987a3df083aSStefano Zampini   PetscErrorCode ierr;
1988a3df083aSStefano Zampini 
1989a3df083aSStefano Zampini   PetscFunctionBegin;
1990a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1991a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1992a3df083aSStefano Zampini   if (is1) {
19937dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1994a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1995a3df083aSStefano Zampini   } else {
1996a3df083aSStefano Zampini     *B = An;
1997a3df083aSStefano Zampini   }
1998a3df083aSStefano Zampini   PetscFunctionReturn(0);
1999a3df083aSStefano Zampini }
2000a3df083aSStefano Zampini 
20011cf9b237SStefano Zampini /* TODO: add reuse flag */
20021cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20031cf9b237SStefano Zampini {
20041cf9b237SStefano Zampini   Mat            Bt;
20051cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20061cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20071cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20081cf9b237SStefano Zampini   PetscBool      flg_row;
20091cf9b237SStefano Zampini   PetscErrorCode ierr;
20101cf9b237SStefano Zampini 
20111cf9b237SStefano Zampini   PetscFunctionBegin;
20121cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20131cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20141cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20151cf9b237SStefano Zampini   nnz = n;
20161cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20171cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
20181cf9b237SStefano Zampini   }
20191cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
20201cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
20211cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
20221cf9b237SStefano Zampini   nnz = 0;
20231cf9b237SStefano Zampini   bii[0] = 0;
20241cf9b237SStefano Zampini   for (i=0;i<n;i++) {
20251cf9b237SStefano Zampini     PetscInt j;
20261cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
20271cf9b237SStefano Zampini       PetscScalar entry = a[j];
20281cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
20291cf9b237SStefano Zampini         bij[nnz] = ij[j];
20301cf9b237SStefano Zampini         bdata[nnz] = entry;
20311cf9b237SStefano Zampini         nnz++;
20321cf9b237SStefano Zampini       }
20331cf9b237SStefano Zampini     }
20341cf9b237SStefano Zampini     bii[i+1] = nnz;
20351cf9b237SStefano Zampini   }
20361cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
20371cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
20381cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20391cf9b237SStefano Zampini   {
20401cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
20411cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
20421cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
20431cf9b237SStefano Zampini   }
20441cf9b237SStefano Zampini   *B = Bt;
20451cf9b237SStefano Zampini   PetscFunctionReturn(0);
20461cf9b237SStefano Zampini }
20471cf9b237SStefano Zampini 
20484f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
20494f1b2e48SStefano Zampini {
20504f1b2e48SStefano Zampini   Mat                    B;
20514f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
20524f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
20534f1b2e48SStefano Zampini   PCBDDCGraph            graph;
20544f1b2e48SStefano Zampini   PetscInt               i,n;
20554f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
20564f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
20574f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
20584f1b2e48SStefano Zampini   PetscErrorCode         ierr;
20594f1b2e48SStefano Zampini 
20604f1b2e48SStefano Zampini   PetscFunctionBegin;
206163c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
206263c961adSStefano Zampini     *ncc = 0;
206363c961adSStefano Zampini     *cc = NULL;
206463c961adSStefano Zampini     PetscFunctionReturn(0);
206563c961adSStefano Zampini   }
20664f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
20674f1b2e48SStefano Zampini   if (!isseqaij && filter) {
20681cf9b237SStefano Zampini     PetscBool isseqdense;
20691cf9b237SStefano Zampini 
20701cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
20711cf9b237SStefano Zampini     if (!isseqdense) {
20724f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
20731cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
20741cf9b237SStefano Zampini       PetscScalar *array;
20751cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
20761cf9b237SStefano Zampini 
20771cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
20781cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
20791cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
20801cf9b237SStefano Zampini       for (i=0;i<n;i++) {
20811cf9b237SStefano Zampini         PetscInt j;
20821cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
20831cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
20841cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
20851cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
20861cf9b237SStefano Zampini         }
20871cf9b237SStefano Zampini       }
20881cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
20899d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
20901cf9b237SStefano Zampini     }
20914f1b2e48SStefano Zampini   } else {
20924f1b2e48SStefano Zampini     B = A;
20934f1b2e48SStefano Zampini   }
20944f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
20954f1b2e48SStefano Zampini 
20964f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
20974f1b2e48SStefano Zampini   if (filter) {
20984f1b2e48SStefano Zampini     PetscScalar *data;
20994f1b2e48SStefano Zampini     PetscInt    j,cum;
21004f1b2e48SStefano Zampini 
21014f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
21024f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
21034f1b2e48SStefano Zampini     cum = 0;
21044f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
21054f1b2e48SStefano Zampini       PetscInt t;
21064f1b2e48SStefano Zampini 
21074f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
21084f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
21094f1b2e48SStefano Zampini           continue;
21104f1b2e48SStefano Zampini         }
21114f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
21124f1b2e48SStefano Zampini       }
21134f1b2e48SStefano Zampini       t = xadj_filtered[i];
21144f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
21154f1b2e48SStefano Zampini       cum += t;
21164f1b2e48SStefano Zampini     }
21174f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
21184f1b2e48SStefano Zampini   } else {
21194f1b2e48SStefano Zampini     xadj_filtered = NULL;
21204f1b2e48SStefano Zampini     adjncy_filtered = NULL;
21214f1b2e48SStefano Zampini   }
21224f1b2e48SStefano Zampini 
21234f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
21244f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
21254f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
21264f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
21274f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2128be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
21294f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
21304f1b2e48SStefano Zampini   if (xadj_filtered) {
21314f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
21324f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
21334f1b2e48SStefano Zampini   } else {
21344f1b2e48SStefano Zampini     graph->xadj = xadj;
21354f1b2e48SStefano Zampini     graph->adjncy = adjncy;
21364f1b2e48SStefano Zampini   }
21374f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
21384f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
21394f1b2e48SStefano Zampini   /* partial clean up */
21404f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
21414f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
21421cf9b237SStefano Zampini   if (A != B) {
21434f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
21444f1b2e48SStefano Zampini   }
21454f1b2e48SStefano Zampini 
21464f1b2e48SStefano Zampini   /* get back data */
21471cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
21481cf9b237SStefano Zampini   if (cc) {
21494f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
21504f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
21514f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
21524f1b2e48SStefano Zampini     }
21534f1b2e48SStefano Zampini     *cc = cc_n;
21541cf9b237SStefano Zampini   }
21554f1b2e48SStefano Zampini   /* clean up graph */
21564f1b2e48SStefano Zampini   graph->xadj = 0;
21574f1b2e48SStefano Zampini   graph->adjncy = 0;
21584f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
21594f1b2e48SStefano Zampini   PetscFunctionReturn(0);
21604f1b2e48SStefano Zampini }
21614f1b2e48SStefano Zampini 
21625408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
21635408967cSStefano Zampini {
21645408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
21655408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2166dee84bffSStefano Zampini   IS             dirIS = NULL;
21674f1b2e48SStefano Zampini   PetscInt       i;
21685408967cSStefano Zampini   PetscErrorCode ierr;
21695408967cSStefano Zampini 
21705408967cSStefano Zampini   PetscFunctionBegin;
2171dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
21725408967cSStefano Zampini   if (zerodiag) {
21735408967cSStefano Zampini     Mat            A;
21745408967cSStefano Zampini     Vec            vec3_N;
21755408967cSStefano Zampini     PetscScalar    *vals;
21765408967cSStefano Zampini     const PetscInt *idxs;
2177d12d3064SStefano Zampini     PetscInt       nz,*count;
21785408967cSStefano Zampini 
21795408967cSStefano Zampini     /* p0 */
21805408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
21815408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
21825408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
21835408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
21844f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
21855408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21865408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
21875408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
21885408967cSStefano Zampini     /* v_I */
21895408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
21905408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
21915408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21925408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
21935408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
21945408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
21955408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21965408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
21975408967cSStefano Zampini     if (dirIS) {
21985408967cSStefano Zampini       PetscInt n;
21995408967cSStefano Zampini 
22005408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
22015408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
22025408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
22035408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
22045408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
22055408967cSStefano Zampini     }
22065408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
22075408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
22085408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
22095408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2210669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
22115408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
22125408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
22139a962809SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)",PetscAbsScalar(vals[0]));
22145408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
22155408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2216d12d3064SStefano Zampini 
2217d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2218d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2219d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2220d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2221d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2222d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
22239a962809SStefano Zampini     for (i=0;i<nz;i++) if (count[idxs[i]]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
2224d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2225d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
22265408967cSStefano Zampini   }
2227dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
22285408967cSStefano Zampini 
22295408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
22305408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
22314f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
22325408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
22334f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
22345408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2235f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2236f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
2237f2a566d8SStefano Zampini     if (val != -PetscGlobalRank-i) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %d instead of %g\n",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i);CHKERRQ(ierr);
2238f2a566d8SStefano Zampini   }
22395408967cSStefano Zampini   PetscFunctionReturn(0);
22405408967cSStefano Zampini }
22415408967cSStefano Zampini 
2242339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2243339f8db1SStefano Zampini {
2244339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
22454edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2246b0f5fe93SStefano Zampini   PetscInt       nz,n;
22474edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
22484edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2249339f8db1SStefano Zampini   PetscErrorCode ierr;
2250339f8db1SStefano Zampini 
2251339f8db1SStefano Zampini   PetscFunctionBegin;
22529f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
22539f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2254a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2255a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2256a3df083aSStefano Zampini   }
2257a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2258a3df083aSStefano Zampini   pcbddc->benign_n = 0;
225928b8efb1Sstefano_zampini 
226028b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
22614f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
22624f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
22634f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
22641ae86dd6SStefano Zampini      since the local Schur complements are already SPD
22654f1b2e48SStefano Zampini   */
22664f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
22674f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
226840fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
22697fbe2174Sstefano_zampini     IS       iP = NULL;
22704f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
22714f1b2e48SStefano Zampini 
227228b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
227328b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
227428b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
227528b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
22764f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
22774f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
22784f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
22794f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2280ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
22817fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
22827fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
22837fbe2174Sstefano_zampini     if (iP) {
22847fbe2174Sstefano_zampini       IS newpressures;
22857fbe2174Sstefano_zampini 
22867fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
22877fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
22887fbe2174Sstefano_zampini       pressures = newpressures;
22897fbe2174Sstefano_zampini     }
229040fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
229140fa8d13SStefano Zampini     if (!sorted) {
229240fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
229340fa8d13SStefano Zampini     }
229440fa8d13SStefano Zampini   } else {
229540fa8d13SStefano Zampini     pressures = NULL;
229640fa8d13SStefano Zampini   }
229797d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
229897d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
229927b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
230097d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2301339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2302339f8db1SStefano Zampini   if (!sorted) {
2303339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2304339f8db1SStefano Zampini   }
23054edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
23064edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2307339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
23084f1b2e48SStefano Zampini   if (!nz) {
23094f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
23104f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
231140fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
231240fa8d13SStefano Zampini   }
23134f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
23144f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
23154f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
23164f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
23171f4df5f7SStefano Zampini   n_interior_dofs  = 0;
23181f4df5f7SStefano Zampini   interior_dofs    = NULL;
23194edc6404Sstefano_zampini   nneu             = 0;
23204edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
23214edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
23224edc6404Sstefano_zampini   }
23233369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
23244edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
23251f4df5f7SStefano Zampini     PetscInt n,i,j;
23261f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
23271f4df5f7SStefano Zampini     PetscInt *iwork;
23281f4df5f7SStefano Zampini 
23291f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
23301f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
23311f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
23321f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
233390648384SStefano Zampini     for (i=1;i<n_neigh;i++)
23341f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
23351f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
23361f4df5f7SStefano Zampini     for (i=0;i<n;i++)
23371f4df5f7SStefano Zampini       if (!iwork[i])
23381f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
23391f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
23401f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
23411f4df5f7SStefano Zampini   }
23424f1b2e48SStefano Zampini   if (has_null_pressures) {
23434f1b2e48SStefano Zampini     IS             *subs;
23444edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
23451f4df5f7SStefano Zampini     const PetscInt *idxs;
23461f4df5f7SStefano Zampini     PetscScalar    *array;
23471f4df5f7SStefano Zampini     Vec            *work;
23481f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
23494f1b2e48SStefano Zampini 
23504f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
23514f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
23521f4df5f7SStefano Zampini     /* these vectors are needed to check if the constant on pressures is in the kernel of the local operator B (i.e. B(v_I,p0) should be zero) */
23534edc6404Sstefano_zampini     if (checkb) {
23541f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
23551f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
23561f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
23571f4df5f7SStefano Zampini       /* work[0] = 1_p */
23581f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
23591f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
23601f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
23611f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
23621f4df5f7SStefano Zampini       /* work[0] = 1_v */
23631f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
23641f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
23651f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
23661f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
23671f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
23681f4df5f7SStefano Zampini     }
23694f1b2e48SStefano Zampini     if (nsubs > 1) {
23704f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
23714f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
23724f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
23734f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
23744f1b2e48SStefano Zampini         PetscInt               nl;
23754f1b2e48SStefano Zampini 
23764f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
23774f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
23784f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
23794f1b2e48SStefano Zampini         if (nl) {
23804f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
23814f1b2e48SStefano Zampini 
23824edc6404Sstefano_zampini           if (checkb) {
23831f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
23841f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
23851f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
23861f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
23871f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
23881f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
23891f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
23901f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
23911f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
23921f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
23931f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
23941f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
23951f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
23961f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
23971f4df5f7SStefano Zampini                 break;
23981f4df5f7SStefano Zampini               }
23991f4df5f7SStefano Zampini             }
24001f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
24011f4df5f7SStefano Zampini           }
24026632bad2Sstefano_zampini           if (valid && nneu) {
24036632bad2Sstefano_zampini             const PetscInt *idxs;
24041f4df5f7SStefano Zampini             PetscInt       nzb;
24051f4df5f7SStefano Zampini 
24066632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
24076632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
24086632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
24091f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
24101f4df5f7SStefano Zampini           }
24111f4df5f7SStefano Zampini           if (valid && pressures) {
24124f1b2e48SStefano Zampini             IS t_pressure_subs;
24134f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
24144f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
24154f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
24164f1b2e48SStefano Zampini           }
24174f1b2e48SStefano Zampini           if (valid) {
24184f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
24194f1b2e48SStefano Zampini             pcbddc->benign_n++;
24204f1b2e48SStefano Zampini           } else {
24214f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
24224f1b2e48SStefano Zampini           }
24234f1b2e48SStefano Zampini         }
24244f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
24254f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
24264f1b2e48SStefano Zampini       }
24274f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
24284f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
24291f4df5f7SStefano Zampini 
24306632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
24311f4df5f7SStefano Zampini       if (valid && pressures) {
24324f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
24334f1b2e48SStefano Zampini       }
24344edc6404Sstefano_zampini       if (valid && checkb) {
24351f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
24361f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
24371f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
24381f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
24391f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
24401f4df5f7SStefano Zampini             valid = PETSC_FALSE;
24411f4df5f7SStefano Zampini             break;
24421f4df5f7SStefano Zampini           }
24431f4df5f7SStefano Zampini         }
24441f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
24451f4df5f7SStefano Zampini       }
24464f1b2e48SStefano Zampini       if (valid) {
24474f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2448ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
24494f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
24504f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
24514f1b2e48SStefano Zampini       }
24524f1b2e48SStefano Zampini     }
24534edc6404Sstefano_zampini     if (checkb) {
24541f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
24554f1b2e48SStefano Zampini     }
24561f4df5f7SStefano Zampini   }
24571f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
24584f1b2e48SStefano Zampini 
24594f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2460b9b0e38cSStefano Zampini     PetscInt n;
2461b9b0e38cSStefano Zampini 
24624f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
24634f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2464b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2465b9b0e38cSStefano Zampini     if (n) {
24664f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
24674f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
24684f1b2e48SStefano Zampini     }
2469b9b0e38cSStefano Zampini   }
24704f1b2e48SStefano Zampini 
24714f1b2e48SStefano Zampini   /* final check for null pressures */
24724f1b2e48SStefano Zampini   if (zerodiag && pressures) {
24734f1b2e48SStefano Zampini     PetscInt nz,np;
24744f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24754f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
24764f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
24774f1b2e48SStefano Zampini   }
24784f1b2e48SStefano Zampini 
24794f1b2e48SStefano Zampini   if (recompute_zerodiag) {
24804f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
24814f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
24824f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
24834f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
24844f1b2e48SStefano Zampini     } else {
24854f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
24864f1b2e48SStefano Zampini 
24874f1b2e48SStefano Zampini       nzn = 0;
24884f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
24894f1b2e48SStefano Zampini         PetscInt ns;
24904f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
24914f1b2e48SStefano Zampini         nzn += ns;
24924f1b2e48SStefano Zampini       }
24934f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
24944f1b2e48SStefano Zampini       nzn = 0;
24954f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
24964f1b2e48SStefano Zampini         PetscInt ns,*idxs;
24974f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
24984f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
24994f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
25004f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
25014f1b2e48SStefano Zampini         nzn += ns;
25024f1b2e48SStefano Zampini       }
25034f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
25044f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
25054f1b2e48SStefano Zampini     }
25064f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
25074f1b2e48SStefano Zampini   }
25084f1b2e48SStefano Zampini 
2509669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2510a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2511a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2512a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2513a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2514a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2515a198735bSStefano Zampini 
25161f4df5f7SStefano Zampini     if (pressures) {
25171f4df5f7SStefano Zampini       isused = pressures;
25181f4df5f7SStefano Zampini     } else {
25194edc6404Sstefano_zampini       isused = zerodiag_save;
25201f4df5f7SStefano Zampini     }
2521a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2522669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
25231ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
25241ae86dd6SStefano Zampini     if (!isused && n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Don't know how to extract div u dot p! Please provide the pressure field");
2525a198735bSStefano Zampini     n_isused = 0;
2526a198735bSStefano Zampini     if (isused) {
2527a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2528a198735bSStefano Zampini     }
2529a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2530a198735bSStefano Zampini     st = st-n_isused;
25311ae86dd6SStefano Zampini     if (n) {
2532a198735bSStefano Zampini       const PetscInt *gidxs;
2533a198735bSStefano Zampini 
25347dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2535a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2536a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2537a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2538a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2539a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
25401ae86dd6SStefano Zampini     } else {
2541a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2542a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2543a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2544a198735bSStefano Zampini     }
2545a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2546a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2547a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2548a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2549a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2550a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2551a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2552a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2553a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2554a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2555a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2556a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2557a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2558a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
25591ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25601ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25611ae86dd6SStefano Zampini   }
25624edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2563b3afcdbeSStefano Zampini 
2564b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
25654f1b2e48SStefano Zampini   if (has_null_pressures) {
25664f1b2e48SStefano Zampini     IS             zerodiagc;
25674f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
25684f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
25694f1b2e48SStefano Zampini 
25704f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2571339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2572339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2573339f8db1SStefano Zampini     /* local change of basis for pressures */
2574339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
257597d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2576339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2577339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2578339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
25794f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
25804f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
25814f1b2e48SStefano Zampini       PetscInt nzs,j;
25824f1b2e48SStefano Zampini 
25834f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
25844f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
25854f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
25864f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
25874f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
25884f1b2e48SStefano Zampini     }
2589339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2590339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2591339f8db1SStefano Zampini     /* set identity on velocities */
2592339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2593339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2594339f8db1SStefano Zampini     }
25954f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
25964f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
25979f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
25984f1b2e48SStefano Zampini     ierr = PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0);CHKERRQ(ierr);
2599339f8db1SStefano Zampini     /* set change on pressures */
26004f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
26014f1b2e48SStefano Zampini       PetscScalar *array;
26024f1b2e48SStefano Zampini       PetscInt    nzs;
26034f1b2e48SStefano Zampini 
26044f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
26054f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
26064f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2607339f8db1SStefano Zampini         PetscScalar vals[2];
2608339f8db1SStefano Zampini         PetscInt    cols[2];
2609339f8db1SStefano Zampini 
2610339f8db1SStefano Zampini         cols[0] = idxs[i];
26114f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2612339f8db1SStefano Zampini         vals[0] = 1.;
2613b0f5fe93SStefano Zampini         vals[1] = 1.;
26144f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2615339f8db1SStefano Zampini       }
26164f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
26174f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
26184f1b2e48SStefano Zampini       array[nzs-1] = 1.;
26194f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
26204f1b2e48SStefano Zampini       /* store local idxs for p0 */
26214f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
26224f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2623339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
26244f1b2e48SStefano Zampini     }
2625339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2626339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2627a3df083aSStefano Zampini     /* project if needed */
2628a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
26291dd7afcfSStefano Zampini       Mat M;
26301dd7afcfSStefano Zampini 
26311dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2632339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
26331dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
26341dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2635a3df083aSStefano Zampini     }
26364f1b2e48SStefano Zampini     /* store global idxs for p0 */
26374f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2638339f8db1SStefano Zampini   }
2639ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
26404f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2641b0f5fe93SStefano Zampini 
2642b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2643b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
264427b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
264527b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2646339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2647339f8db1SStefano Zampini   PetscFunctionReturn(0);
2648339f8db1SStefano Zampini }
2649339f8db1SStefano Zampini 
2650015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2651efc2fbd9SStefano Zampini {
2652efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2653de9d7bd0SStefano Zampini   PetscScalar    *array;
2654efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2655efc2fbd9SStefano Zampini 
2656efc2fbd9SStefano Zampini   PetscFunctionBegin;
2657efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2658efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
26594f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2660efc2fbd9SStefano Zampini   }
2661de9d7bd0SStefano Zampini   if (get) {
2662efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
26634f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
26644f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2665efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2666de9d7bd0SStefano Zampini   } else {
2667de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2668de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2669de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2670de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2671efc2fbd9SStefano Zampini   }
2672efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2673efc2fbd9SStefano Zampini }
2674efc2fbd9SStefano Zampini 
2675c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2676c263805aSStefano Zampini {
2677c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2678c263805aSStefano Zampini   PetscErrorCode ierr;
2679c263805aSStefano Zampini 
2680c263805aSStefano Zampini   PetscFunctionBegin;
2681c263805aSStefano Zampini   /* TODO: add error checking
2682c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2683c263805aSStefano Zampini     - cannot push before pop.
26841c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2685c263805aSStefano Zampini   */
26864f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2687efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2688efc2fbd9SStefano Zampini   }
2689c263805aSStefano Zampini   if (pop) {
2690a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
26914f1b2e48SStefano Zampini       IS       is_p0;
26924f1b2e48SStefano Zampini       MatReuse reuse;
2693c263805aSStefano Zampini 
2694c263805aSStefano Zampini       /* extract B_0 */
26954f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
26964f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
26974f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
26984f1b2e48SStefano Zampini       }
26994f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
27007dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2701c263805aSStefano Zampini       /* remove rows and cols from local problem */
2702c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
270397d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
27054f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2706a3df083aSStefano Zampini     } else {
2707a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2708a3df083aSStefano Zampini       PetscScalar *vals;
2709a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2710a3df083aSStefano Zampini 
2711a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2712a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2713a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
27140b5adadeSStefano Zampini         PetscInt *nnz;
2715a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2716a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2717a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2718331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2719331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2720331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2721331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2722331e053bSStefano Zampini         }
2723331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2724331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2725331e053bSStefano Zampini       }
2726a3df083aSStefano Zampini 
2727a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2728a3df083aSStefano Zampini         PetscScalar *array;
2729a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2730a3df083aSStefano Zampini 
2731a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2732a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2733a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2734a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2735a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2736a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2737a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2738a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2739a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2740a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2741a3df083aSStefano Zampini         cum = 0;
2742a3df083aSStefano Zampini         for (j=0;j<n;j++) {
274322db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2744a3df083aSStefano Zampini             vals[cum] = array[j];
2745a3df083aSStefano Zampini             idxs_ins[cum] = j;
2746a3df083aSStefano Zampini             cum++;
2747a3df083aSStefano Zampini           }
2748a3df083aSStefano Zampini         }
2749a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2750a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2751a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2752a3df083aSStefano Zampini       }
2753a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2754a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2755a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2756a3df083aSStefano Zampini     }
2757c263805aSStefano Zampini   } else { /* push */
2758a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
27594f1b2e48SStefano Zampini       PetscInt i;
27604f1b2e48SStefano Zampini 
27614f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27624f1b2e48SStefano Zampini         PetscScalar *B0_vals;
27634f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
27644f1b2e48SStefano Zampini 
27654f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
27664f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
27677b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
27684f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
27694f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
27704f1b2e48SStefano Zampini       }
2771c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2772c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2773a3df083aSStefano Zampini     } else {
2774a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2775a3df083aSStefano Zampini     }
2776c263805aSStefano Zampini   }
2777c263805aSStefano Zampini   PetscFunctionReturn(0);
2778c263805aSStefano Zampini }
2779c263805aSStefano Zampini 
278008122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2781b1b3d7a2SStefano Zampini {
2782b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
278308122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
278408122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
278508122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
278608122e43SStefano Zampini   PetscScalar     *work,lwork;
278708122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
278808122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
278908122e43SStefano Zampini   PetscReal       *eigs,thresh;
27901b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2791f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
279208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
279308122e43SStefano Zampini   PetscReal       *rwork;
279408122e43SStefano Zampini #endif
2795b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2796b1b3d7a2SStefano Zampini 
2797b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2798b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2799af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2800d750e150Sstefano_zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for general matrix pencils (herm %d, posdef %d)\nRerun with -sub_schurs_hermitian 1 -sub_schurs_posdef 1 if the problem is SPD",sub_schurs->is_hermitian,sub_schurs->is_posdef);
280106a4e24aSStefano Zampini 
2802fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2803fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2804fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2805fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
28061575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2807fd14bc51SStefano Zampini   }
2808fd14bc51SStefano Zampini 
2809e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2810e496cd5dSStefano Zampini     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
2811e496cd5dSStefano Zampini   }
2812e496cd5dSStefano Zampini 
281308122e43SStefano Zampini   /* max size of subsets */
281408122e43SStefano Zampini   mss = 0;
281508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
281608122e43SStefano Zampini     PetscInt subset_size;
2817862806e4SStefano Zampini 
281808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
281908122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
282008122e43SStefano Zampini   }
282108122e43SStefano Zampini 
282208122e43SStefano Zampini   /* min/max and threshold */
282308122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2824f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
282508122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2826f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2827f6f667cfSStefano Zampini   if (nmin) {
2828f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2829f6f667cfSStefano Zampini   }
283008122e43SStefano Zampini 
283108122e43SStefano Zampini   /* allocate lapack workspace */
283208122e43SStefano Zampini   cum = cum2 = 0;
283308122e43SStefano Zampini   maxneigs = 0;
283408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
283508122e43SStefano Zampini     PetscInt n,subset_size;
2836f6f667cfSStefano Zampini 
283708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
283808122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
28399162d606SStefano Zampini     cum += subset_size;
28409162d606SStefano Zampini     cum2 += subset_size*n;
284108122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
284208122e43SStefano Zampini   }
284308122e43SStefano Zampini   if (mss) {
28449ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
284508122e43SStefano Zampini       PetscBLASInt B_itype = 1;
284608122e43SStefano Zampini       PetscBLASInt B_N = mss;
28474c6709b3SStefano Zampini       PetscReal    zero = 0.0;
28484c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
284908122e43SStefano Zampini 
285008122e43SStefano Zampini       B_lwork = -1;
285108122e43SStefano Zampini       S = NULL;
285208122e43SStefano Zampini       St = NULL;
2853a58a30b4SStefano Zampini       eigs = NULL;
2854a58a30b4SStefano Zampini       eigv = NULL;
2855a58a30b4SStefano Zampini       B_iwork = NULL;
2856a58a30b4SStefano Zampini       B_ifail = NULL;
2857d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2858d1710679SStefano Zampini       rwork = NULL;
2859d1710679SStefano Zampini #endif
28608bec7fa6SStefano Zampini       thresh = 1.0;
286108122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
286208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
286308122e43SStefano Zampini       PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_dummyint,&B_dummyint,&eps,&B_neigs,eigs,eigv,&B_N,&lwork,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
286408122e43SStefano Zampini #else
286508122e43SStefano Zampini       PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_dummyint,&B_dummyint,&eps,&B_neigs,eigs,eigv,&B_N,&lwork,&B_lwork,B_iwork,B_ifail,&B_ierr));
286608122e43SStefano Zampini #endif
286708122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
286808122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
286908122e43SStefano Zampini     } else {
287008122e43SStefano Zampini         /* TODO */
287108122e43SStefano Zampini     }
287208122e43SStefano Zampini   } else {
287308122e43SStefano Zampini     lwork = 0;
287408122e43SStefano Zampini   }
287508122e43SStefano Zampini 
287608122e43SStefano Zampini   nv = 0;
2877d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) { /* complement set of active subsets, each entry is a vertex (boundary made by active subsets, vertices and dirichlet dofs) */
2878d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
287908122e43SStefano Zampini   }
28804c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2881f6f667cfSStefano Zampini   if (allocated_S_St) {
2882f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2883f6f667cfSStefano Zampini   }
2884f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
288508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
288608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
288708122e43SStefano Zampini #endif
28889162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
28899162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
28909162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
289108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
28929162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
289308122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
289408122e43SStefano Zampini 
289508122e43SStefano Zampini   maxneigs = 0;
289672b8c272SStefano Zampini   cum = cumarray = 0;
28979162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
28989162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2899d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
290008122e43SStefano Zampini     const PetscInt *idxs;
290108122e43SStefano Zampini 
2902d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
290308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
290408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
290508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
290608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
29079162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
29089162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
290908122e43SStefano Zampini     }
2910d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
291108122e43SStefano Zampini   }
291208122e43SStefano Zampini 
291308122e43SStefano Zampini   if (mss) { /* multilevel */
291408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
291508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
291608122e43SStefano Zampini   }
291708122e43SStefano Zampini 
2918ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
291908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
292008122e43SStefano Zampini     const PetscInt *idxs;
29219d54b7f4SStefano Zampini     PetscReal      upper,lower;
2922862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
292308122e43SStefano Zampini     PetscBLASInt   B_N;
2924aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
292508122e43SStefano Zampini 
29269d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
29279d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
29289d54b7f4SStefano Zampini       lower = thresh;
29299d54b7f4SStefano Zampini     } else {
29309d54b7f4SStefano Zampini       upper = 1./thresh;
29319d54b7f4SStefano Zampini       lower = 0.;
29329d54b7f4SStefano Zampini     }
2933862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2934ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2935f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2936f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
29379ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2938aff50787SStefano Zampini         PetscInt j,k;
2939aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2940aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2941aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
294208122e43SStefano Zampini         }
294308122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2944aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2945aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2946aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2947aff50787SStefano Zampini           }
294808122e43SStefano Zampini         }
294908122e43SStefano Zampini       } else {
295008122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
295108122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
295208122e43SStefano Zampini       }
29538bec7fa6SStefano Zampini     } else {
2954f6f667cfSStefano Zampini       S = Sarray + cumarray;
2955f6f667cfSStefano Zampini       St = Starray + cumarray;
29568bec7fa6SStefano Zampini     }
2957aff50787SStefano Zampini     /* see if we can save some work */
2958b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2959aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2960aff50787SStefano Zampini     }
2961aff50787SStefano Zampini 
2962b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2963aff50787SStefano Zampini       B_neigs = 0;
2964aff50787SStefano Zampini     } else {
29659ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
296608122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2967f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
29684c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
29699552c7c7SStefano Zampini         PetscInt     nmin_s;
2970b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
297108122e43SStefano Zampini 
2972fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2973eee23b56SStefano Zampini           PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d size %d count %d fid %d.\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]+1,pcbddc->mat_graph->which_dof[idxs[0]]);
2974fd14bc51SStefano Zampini         }
2975d16cbb6bSStefano Zampini 
2976b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2977b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2978b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2979b7ab4a40SStefano Zampini         }
2980b7ab4a40SStefano Zampini 
298108122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2982b7ab4a40SStefano Zampini         if (compute_range) {
2983d16cbb6bSStefano Zampini 
2984d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
298508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29869d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
298708122e43SStefano Zampini #else
29889d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
298908122e43SStefano Zampini #endif
2990b7ab4a40SStefano Zampini         } else if (!same_data) {
2991d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2992d16cbb6bSStefano Zampini           B_IL = 1;
2993d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
29949d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
2995d16cbb6bSStefano Zampini #else
29969d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
2997d16cbb6bSStefano Zampini #endif
2998b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
2999b7ab4a40SStefano Zampini           PetscInt k;
3000b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3001b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3002b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3003b7ab4a40SStefano Zampini           nmin = nmax;
3004b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3005b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3006b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3007b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3008b7ab4a40SStefano Zampini           }
3009d16cbb6bSStefano Zampini         }
301008122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
301108122e43SStefano Zampini         if (B_ierr) {
30126c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
30136c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
30146c4ed002SBarry Smith           else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
301508122e43SStefano Zampini         }
301608122e43SStefano Zampini 
301708122e43SStefano Zampini         if (B_neigs > nmax) {
3018fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3019fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
3020fd14bc51SStefano Zampini           }
30219d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
302208122e43SStefano Zampini           B_neigs = nmax;
302308122e43SStefano Zampini         }
302408122e43SStefano Zampini 
30259552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
30269552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
302708122e43SStefano Zampini           PetscBLASInt B_neigs2;
302808122e43SStefano Zampini 
30299d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3030f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
30319d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
30329d54b7f4SStefano Zampini           } else {
30339d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
30349d54b7f4SStefano Zampini             B_IU = nmin_s;
30359d54b7f4SStefano Zampini           }
3036fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3037fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %d. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);
3038fd14bc51SStefano Zampini           }
30399ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
30401ae86dd6SStefano Zampini             PetscInt j,k;
304108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
30421ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
30431ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
30441ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
304508122e43SStefano Zampini               }
304608122e43SStefano Zampini             }
304708122e43SStefano Zampini           } else {
304808122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
304908122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
305008122e43SStefano Zampini           }
305108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
305208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
30539d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
305408122e43SStefano Zampini #else
30559d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
305608122e43SStefano Zampini #endif
305708122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
305808122e43SStefano Zampini           B_neigs += B_neigs2;
305908122e43SStefano Zampini         }
306008122e43SStefano Zampini         if (B_ierr) {
30616c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
30626c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
30636c4ed002SBarry Smith           else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
306408122e43SStefano Zampini         }
3065fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3066ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
306708122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
306808122e43SStefano Zampini             if (eigs[j] == 0.0) {
3069ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
307008122e43SStefano Zampini             } else {
30719d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3072ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
30739d54b7f4SStefano Zampini               } else {
30749d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
30759d54b7f4SStefano Zampini               }
3076fd14bc51SStefano Zampini             }
307708122e43SStefano Zampini           }
307808122e43SStefano Zampini         }
307908122e43SStefano Zampini       } else {
308008122e43SStefano Zampini           /* TODO */
308108122e43SStefano Zampini       }
3082aff50787SStefano Zampini     }
30836c3e6151SStefano Zampini     /* change the basis back to the original one */
30846c3e6151SStefano Zampini     if (sub_schurs->change) {
308572b8c272SStefano Zampini       Mat change,phi,phit;
30866c3e6151SStefano Zampini 
30876c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
30886c3e6151SStefano Zampini         PetscInt ii;
30896c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
30906c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
30916c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3092684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3093684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3094684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3095684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3096684229deSStefano Zampini #else
30976c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3098684229deSStefano Zampini #endif
30996c3e6151SStefano Zampini           }
31006c3e6151SStefano Zampini         }
31016c3e6151SStefano Zampini       }
310272b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
31036c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
310472b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
31056c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
31066c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
31076c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
31086c3e6151SStefano Zampini     }
31098bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
31108bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
31119162d606SStefano Zampini     if (B_neigs) {
31129162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3113fd14bc51SStefano Zampini 
3114fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
31159552c7c7SStefano Zampini         PetscInt ii;
31169552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3117ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
31189552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3119ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3120ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3121ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3122ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3123ac47001eSStefano Zampini #else
3124ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);CHKERRQ(ierr);
3125ac47001eSStefano Zampini #endif
31269552c7c7SStefano Zampini           }
31279552c7c7SStefano Zampini         }
3128fd14bc51SStefano Zampini       }
31299162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
31309162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
31319162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
31329162d606SStefano Zampini       cum++;
313308122e43SStefano Zampini     }
313408122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
313508122e43SStefano Zampini     /* shift for next computation */
313608122e43SStefano Zampini     cumarray += subset_size*subset_size;
313708122e43SStefano Zampini   }
3138fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3139fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3140fd14bc51SStefano Zampini   }
314108122e43SStefano Zampini 
314208122e43SStefano Zampini   if (mss) {
314308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
314408122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3145f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3146f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3147f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
314808122e43SStefano Zampini   }
3149f6f667cfSStefano Zampini   if (allocated_S_St) {
3150f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3151f6f667cfSStefano Zampini   }
3152f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
315308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
315408122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
315508122e43SStefano Zampini #endif
315608122e43SStefano Zampini   if (pcbddc->dbg_flag) {
31571b968477SStefano Zampini     PetscInt maxneigs_r;
3158b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
31599b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
316008122e43SStefano Zampini   }
316108122e43SStefano Zampini   PetscFunctionReturn(0);
316208122e43SStefano Zampini }
3163b1b3d7a2SStefano Zampini 
3164c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3165c8587f34SStefano Zampini {
31668629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3167c8587f34SStefano Zampini   PetscErrorCode ierr;
3168c8587f34SStefano Zampini 
3169c8587f34SStefano Zampini   PetscFunctionBegin;
3170f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
31715e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3172c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3173c8587f34SStefano Zampini 
3174684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
31750fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3176684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3177c8587f34SStefano Zampini 
31788629588bSStefano Zampini   /*
31798629588bSStefano Zampini      Setup local correction and local part of coarse basis.
31808629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
31818629588bSStefano Zampini   */
318247f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
31838629588bSStefano Zampini 
31848629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
31858629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
31868629588bSStefano Zampini 
31878629588bSStefano Zampini   /* free */
31888629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3189c8587f34SStefano Zampini   PetscFunctionReturn(0);
3190c8587f34SStefano Zampini }
3191c8587f34SStefano Zampini 
3192674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3193674ae819SStefano Zampini {
3194674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3195674ae819SStefano Zampini   PetscErrorCode ierr;
3196674ae819SStefano Zampini 
3197674ae819SStefano Zampini   PetscFunctionBegin;
3198674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
319930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3200674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3201785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3202674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3203f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3204f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3205785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
320663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
320763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3208674ae819SStefano Zampini   PetscFunctionReturn(0);
3209674ae819SStefano Zampini }
3210674ae819SStefano Zampini 
3211674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3212674ae819SStefano Zampini {
3213674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
32144f1b2e48SStefano Zampini   PetscInt       i;
3215674ae819SStefano Zampini   PetscErrorCode ierr;
3216674ae819SStefano Zampini 
3217674ae819SStefano Zampini   PetscFunctionBegin;
32181e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
32191e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3220a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3221b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3222674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
322316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
32241dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3225674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3226669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3227fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
32289326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
32294f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
32304f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
32314f1b2e48SStefano Zampini   }
3232e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
32334f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3234e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3235c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
32368af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3237674ae819SStefano Zampini   PetscFunctionReturn(0);
3238674ae819SStefano Zampini }
3239674ae819SStefano Zampini 
3240674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3241674ae819SStefano Zampini {
3242674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3243674ae819SStefano Zampini   PetscErrorCode ierr;
3244674ae819SStefano Zampini 
3245674ae819SStefano Zampini   PetscFunctionBegin;
3246674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
324758da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3248ca92afb2SStefano Zampini     PetscScalar *array;
324906656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
325006656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
325158da7f69SStefano Zampini   }
3252674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3253674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
325415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
325515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3256674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3257674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3258674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
325906656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3260674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3261674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
32628ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3263674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3264674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3265674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
32669326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
32679326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
32689326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3269f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3270727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
32710e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3272f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
327370cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
327481d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
32750369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
32761dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
32774f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
32788b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3279ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3280ca92afb2SStefano Zampini     PetscInt i;
3281ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3282ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3283ca92afb2SStefano Zampini     }
3284ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3285ca92afb2SStefano Zampini   }
32864f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3287674ae819SStefano Zampini   PetscFunctionReturn(0);
3288674ae819SStefano Zampini }
3289674ae819SStefano Zampini 
3290f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
32916bfb1811SStefano Zampini {
32926bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
32936bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
32946bfb1811SStefano Zampini   VecType        impVecType;
32954f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
32966bfb1811SStefano Zampini   PetscErrorCode ierr;
32976bfb1811SStefano Zampini 
32986bfb1811SStefano Zampini   PetscFunctionBegin;
32994f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3300b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
33016bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3302e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3303e7b262bdSStefano Zampini   /* R nodes */
3304e7b262bdSStefano Zampini   old_size = -1;
3305e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3306e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3307e7b262bdSStefano Zampini   }
3308e7b262bdSStefano Zampini   if (n_R != old_size) {
3309e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3310e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
33116bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
33126bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
33136bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
33146bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3315e7b262bdSStefano Zampini   }
3316e7b262bdSStefano Zampini   /* local primal dofs */
3317e7b262bdSStefano Zampini   old_size = -1;
3318e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3319e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3320e7b262bdSStefano Zampini   }
3321e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3322e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
332383b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3324e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
33256bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3326e7b262bdSStefano Zampini   }
3327e7b262bdSStefano Zampini   /* local explicit constraints */
3328e7b262bdSStefano Zampini   old_size = -1;
3329e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3330e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3331e7b262bdSStefano Zampini   }
3332e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3333e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
333483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
333583b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
333683b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
333783b7ccabSStefano Zampini   }
33386bfb1811SStefano Zampini   PetscFunctionReturn(0);
33396bfb1811SStefano Zampini }
33406bfb1811SStefano Zampini 
334147f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
334288ebb749SStefano Zampini {
334325084f0cSStefano Zampini   PetscErrorCode  ierr;
334425084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
334588ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
334688ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3347d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
334825084f0cSStefano Zampini   /* submatrices of local problem */
334980677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
335006656605SStefano Zampini   /* submatrices of local coarse problem */
335106656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
335225084f0cSStefano Zampini   /* working matrices */
335306656605SStefano Zampini   Mat             C_CR;
335425084f0cSStefano Zampini   /* additional working stuff */
335506656605SStefano Zampini   PC              pc_R;
3356c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
33575cbda25cSStefano Zampini   Vec             dummy_vec;
3358c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
335925084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
336006656605SStefano Zampini   PetscScalar     *work;
336106656605SStefano Zampini   PetscInt        *idx_V_B;
3362ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
336306656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3364ffd830a3SStefano Zampini 
336525084f0cSStefano Zampini   /* some shortcuts to scalars */
336606656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
336788ebb749SStefano Zampini 
336888ebb749SStefano Zampini   PetscFunctionBegin;
33699a962809SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
3370ffd830a3SStefano Zampini 
3371ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3372b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
33734f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3374b371cd4fSStefano Zampini   n_B = pcis->n_B;
3375b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
337688ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
337788ebb749SStefano Zampini 
337888ebb749SStefano Zampini   /* vertices in boundary numbering */
3379785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
33800e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
33816c4ed002SBarry Smith   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",n_vertices,i);
338288ebb749SStefano Zampini 
338306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3384019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
338506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
338606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
338706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
338806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
338906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
339006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
339106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
339206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
339306656605SStefano Zampini 
339406656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
339506656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
339606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
339706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
339806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3399ffd830a3SStefano Zampini   lda_rhs = n_R;
3400a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
340106656605SStefano Zampini   if (isLU || isILU || isCHOL) {
340206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3403b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3404df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3405d62866d3SStefano Zampini     MatFactorType      type;
3406d62866d3SStefano Zampini 
3407df4d28bfSStefano Zampini     F = reuse_solver->F;
34086816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3409d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3410ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
341122db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
341206656605SStefano Zampini   } else {
341306656605SStefano Zampini     F = NULL;
341406656605SStefano Zampini   }
341506656605SStefano Zampini 
3416c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3417c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3418c58f9fdbSStefano Zampini   if (F) {
3419c58f9fdbSStefano Zampini     const MatSolverPackage solver;
3420c58f9fdbSStefano Zampini 
3421c58f9fdbSStefano Zampini     ierr = MatFactorGetSolverPackage(F,&solver);CHKERRQ(ierr);
3422c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3423c58f9fdbSStefano Zampini   }
3424c58f9fdbSStefano Zampini 
3425ffd830a3SStefano Zampini   /* allocate workspace */
3426ffd830a3SStefano Zampini   n = 0;
3427ffd830a3SStefano Zampini   if (n_constraints) {
3428ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3429ffd830a3SStefano Zampini   }
3430ffd830a3SStefano Zampini   if (n_vertices) {
3431ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3432ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3433ffd830a3SStefano Zampini   }
34342a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
34352a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
34362a3a6641Sstefano_zampini   }
3437ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3438ffd830a3SStefano Zampini 
34395cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
34405cbda25cSStefano Zampini   dummy_vec = NULL;
34415cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
34425cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
34435cbda25cSStefano Zampini   }
34445cbda25cSStefano Zampini 
344588ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
344688ebb749SStefano Zampini   if (n_constraints) {
344772b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
344806656605SStefano Zampini     IS          is_aux;
344980677318SStefano Zampini     PetscScalar *array,*array2;
345006656605SStefano Zampini 
3451f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
345280677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
345388ebb749SStefano Zampini 
345425084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
345525084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
34567dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
34577dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
345888ebb749SStefano Zampini 
345980677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
346080677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3461c58f9fdbSStefano Zampini     if (!sparserhs) {
3462ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
346388ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
346406656605SStefano Zampini         const PetscScalar *row_cmat_values;
346506656605SStefano Zampini         const PetscInt    *row_cmat_indices;
346606656605SStefano Zampini         PetscInt          size_of_constraint,j;
346788ebb749SStefano Zampini 
346806656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
346906656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3470ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
347106656605SStefano Zampini         }
347206656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
347306656605SStefano Zampini       }
3474c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3475c58f9fdbSStefano Zampini     } else {
3476c58f9fdbSStefano Zampini       Mat tC_CR;
3477c58f9fdbSStefano Zampini 
3478c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3479c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3480c58f9fdbSStefano Zampini         PetscScalar *aa;
3481c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3482c58f9fdbSStefano Zampini         PetscBool   done;
3483c58f9fdbSStefano Zampini 
3484c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
3485c58f9fdbSStefano Zampini         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");CHKERRQ(ierr);
3486c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3487c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3488c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
3489c58f9fdbSStefano Zampini         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");CHKERRQ(ierr);
3490c58f9fdbSStefano Zampini       } else {
3491c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3492c58f9fdbSStefano Zampini         tC_CR = C_CR;
3493c58f9fdbSStefano Zampini       }
3494c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3495c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3496c58f9fdbSStefano Zampini     }
3497ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
349806656605SStefano Zampini     if (F) {
3499a3df083aSStefano Zampini       if (need_benign_correction) {
3500df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3501a3df083aSStefano Zampini 
350272b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
350372b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3504a3df083aSStefano Zampini       }
3505c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3506a3df083aSStefano Zampini       if (need_benign_correction) {
3507a3df083aSStefano Zampini         PetscScalar        *marr;
3508df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3509a3df083aSStefano Zampini 
3510a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
35115cbda25cSStefano Zampini         if (lda_rhs != n_R) {
35125cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
35135cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
35145cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
35155cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
35165cbda25cSStefano Zampini           }
35175cbda25cSStefano Zampini         } else {
3518a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3519a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
35205cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3521a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3522a3df083aSStefano Zampini           }
35235cbda25cSStefano Zampini         }
3524a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3525a3df083aSStefano Zampini       }
352606656605SStefano Zampini     } else {
352780677318SStefano Zampini       PetscScalar *marr;
352880677318SStefano Zampini 
352980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
353006656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3531ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3532ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
353306656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
353406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
353506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
353606656605SStefano Zampini       }
353780677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
353806656605SStefano Zampini     }
3539c58f9fdbSStefano Zampini     if (sparserhs) {
3540c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3541c58f9fdbSStefano Zampini     }
3542c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
354380677318SStefano Zampini     if (!pcbddc->switch_static) {
354480677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
354580677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
354680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
354780677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3548ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
354980677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
355080677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
355180677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
355280677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
355380677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
355480677318SStefano Zampini       }
355580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
355680677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
355772b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
355880677318SStefano Zampini     } else {
3559ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3560ffd830a3SStefano Zampini         IS dummy;
3561ffd830a3SStefano Zampini 
3562ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
35637dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3564ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3565ffd830a3SStefano Zampini       } else {
356680677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
356780677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3568ffd830a3SStefano Zampini       }
356925084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
357080677318SStefano Zampini     }
357180677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
357280677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
357380677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
357406656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
357506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
357680677318SStefano Zampini     if (isCHOL) {
357780677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
357880677318SStefano Zampini     } else {
357925084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
358080677318SStefano Zampini     }
358180677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
358206656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
358325084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
358425084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
358525084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
358680677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
358772b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
358872b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
358906656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
359006656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3591f4ddd8eeSStefano Zampini   }
3592fc227af8SStefano Zampini 
3593fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
359488ebb749SStefano Zampini   if (n_vertices) {
359506656605SStefano Zampini     IS        is_aux;
3596c58f9fdbSStefano Zampini     PetscBool isseqaij;
35973a50541eSStefano Zampini 
3598b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
35996816873aSStefano Zampini       IS tis;
36006816873aSStefano Zampini 
36016816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
36026816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
36036816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
36046816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
36056816873aSStefano Zampini     } else {
36063a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
36076816873aSStefano Zampini     }
36087dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
36097dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3610c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3611c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
3612c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3613c58f9fdbSStefano Zampini     }
36147dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
361525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
361688ebb749SStefano Zampini   }
361788ebb749SStefano Zampini 
361888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3619f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
362006656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
362106656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
362206656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
362306656605SStefano Zampini     }
3624f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
362506656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
362606656605SStefano Zampini       PetscScalar *marray;
362706656605SStefano Zampini 
362806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
362906656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3630f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3631f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3632f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3633f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3634f4ddd8eeSStefano Zampini     }
3635f4ddd8eeSStefano Zampini   }
363606656605SStefano Zampini 
3637f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
3638a6e023c1Sstefano_zampini     PetscScalar *marr;
363988ebb749SStefano Zampini 
3640a6e023c1Sstefano_zampini     /* memory size */
364106656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
3642a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
3643a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
3644a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
3645a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3646a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
36478eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3648a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3649a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
365088ebb749SStefano Zampini     }
36513301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
3652a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3653a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
36548eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3655a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
365688ebb749SStefano Zampini       }
365788ebb749SStefano Zampini     } else {
3658c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3659c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
36601b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3661c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3662c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3663c0553b1fSStefano Zampini       }
366488ebb749SStefano Zampini     }
366506656605SStefano Zampini   }
3666019a44ceSStefano Zampini 
366706656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
36684f1b2e48SStefano Zampini   p0_lidx_I = NULL;
36694f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3670d12edf2fSStefano Zampini     const PetscInt *idxs;
3671d12edf2fSStefano Zampini 
3672d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
36734f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
36744f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
36754f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
36764f1b2e48SStefano Zampini     }
3677d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3678d12edf2fSStefano Zampini   }
3679d16cbb6bSStefano Zampini 
368006656605SStefano Zampini   /* vertices */
368106656605SStefano Zampini   if (n_vertices) {
3682c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
368316f15bc4SStefano Zampini 
3684af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
368504708bb6SStefano Zampini 
368616f15bc4SStefano Zampini     if (n_R) {
368714393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
368806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
368916f15bc4SStefano Zampini       PetscScalar  *x,*y;
369006656605SStefano Zampini 
369121eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
369214393ed6SStefano Zampini       if (need_benign_correction) {
369314393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
369414393ed6SStefano Zampini         IS                     is_p0;
369514393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
369614393ed6SStefano Zampini 
369714393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
369814393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
369914393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3700af25d912SStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
370114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
370214393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
37037dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
370414393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
370514393ed6SStefano Zampini       }
370614393ed6SStefano Zampini 
3707c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3708c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
3709ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
3710af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3711ffd830a3SStefano Zampini         } else {
3712ca92afb2SStefano Zampini           PetscScalar    *av,*array;
3713ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
3714ca92afb2SStefano Zampini           PetscInt       n;
3715ca92afb2SStefano Zampini           PetscBool      flg_row;
3716ffd830a3SStefano Zampini 
3717ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
3718ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
37199d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3720ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3721ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3722ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
3723ca92afb2SStefano Zampini             PetscInt j;
3724ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3725ffd830a3SStefano Zampini           }
3726ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3727ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3728ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3729ffd830a3SStefano Zampini         }
3730a3df083aSStefano Zampini         if (need_benign_correction) {
3731df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3732a3df083aSStefano Zampini           PetscScalar        *marr;
3733a3df083aSStefano Zampini 
3734a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
373514393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
373614393ed6SStefano Zampini 
373714393ed6SStefano Zampini                  | 0 0  0 | (V)
373814393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
373914393ed6SStefano Zampini                  | 0 0 -1 | (p0)
374014393ed6SStefano Zampini 
374114393ed6SStefano Zampini           */
3742df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
374314393ed6SStefano Zampini             const PetscScalar *vals;
374414393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
374514393ed6SStefano Zampini             PetscInt          n,j,nz;
374614393ed6SStefano Zampini 
3747df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3748df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
374914393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
375014393ed6SStefano Zampini             for (j=0;j<n;j++) {
375114393ed6SStefano Zampini               PetscScalar val = vals[j];
375214393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
375314393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
375414393ed6SStefano Zampini             }
375514393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3756df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
375714393ed6SStefano Zampini           }
375872b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
375972b8c272SStefano Zampini         }
3760c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
3761c58f9fdbSStefano Zampini         Brhs = A_RV;
3762c58f9fdbSStefano Zampini       } else {
3763c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
3764c58f9fdbSStefano Zampini 
3765c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
3766c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
3767c58f9fdbSStefano Zampini         } else {
3768c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
3769c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
3770c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
3771c58f9fdbSStefano Zampini           A_RVT = A_VR;
3772c58f9fdbSStefano Zampini         }
3773c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
3774c58f9fdbSStefano Zampini           PetscScalar *aa;
3775c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
3776c58f9fdbSStefano Zampini           PetscBool   done;
3777c58f9fdbSStefano Zampini 
3778c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
3779c58f9fdbSStefano Zampini           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");CHKERRQ(ierr);
3780c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
3781c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
3782c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
3783c58f9fdbSStefano Zampini           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");CHKERRQ(ierr);
3784c58f9fdbSStefano Zampini         } else {
3785c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
3786c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
3787c58f9fdbSStefano Zampini         }
3788c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
3789c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
3790c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
3791c58f9fdbSStefano Zampini       }
379272b8c272SStefano Zampini       if (F) {
379314393ed6SStefano Zampini         /* need to correct the rhs */
379472b8c272SStefano Zampini         if (need_benign_correction) {
379572b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
379672b8c272SStefano Zampini           PetscScalar        *marr;
379772b8c272SStefano Zampini 
3798c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
37995cbda25cSStefano Zampini           if (lda_rhs != n_R) {
38005cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
38015cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
38025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
38035cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
38045cbda25cSStefano Zampini             }
38055cbda25cSStefano Zampini           } else {
3806a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3807a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
38085cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3809a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3810a3df083aSStefano Zampini             }
38115cbda25cSStefano Zampini           }
3812c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
3813a3df083aSStefano Zampini         }
3814c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
3815c58f9fdbSStefano Zampini         if (restoreavr) {
3816c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
3817c58f9fdbSStefano Zampini         }
381814393ed6SStefano Zampini         /* need to correct the solution */
3819a3df083aSStefano Zampini         if (need_benign_correction) {
3820df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3821a3df083aSStefano Zampini           PetscScalar        *marr;
3822a3df083aSStefano Zampini 
3823a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
38245cbda25cSStefano Zampini           if (lda_rhs != n_R) {
38255cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
38265cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
38275cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
38285cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
38295cbda25cSStefano Zampini             }
38305cbda25cSStefano Zampini           } else {
3831a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3832a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
38335cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3834a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3835a3df083aSStefano Zampini             }
38365cbda25cSStefano Zampini           }
3837a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3838a3df083aSStefano Zampini         }
383906656605SStefano Zampini       } else {
3840c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
384106656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3842ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3843ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
384406656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
384506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
384606656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
384706656605SStefano Zampini         }
3848c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
384906656605SStefano Zampini       }
385080677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3851c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
3852ffd830a3SStefano Zampini       /* S_VV and S_CV */
385306656605SStefano Zampini       if (n_constraints) {
385406656605SStefano Zampini         Mat B;
385580677318SStefano Zampini 
3856ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
385780677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3858ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3859ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
386080677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
386180677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
386280677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
386380677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
386480677318SStefano Zampini         }
3865ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
386680677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
386780677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3868ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
386980677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
387006656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3871ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3872ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
387306656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
387406656605SStefano Zampini       }
3875ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3876ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3877ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3878ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3879ffd830a3SStefano Zampini       }
388006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
388114393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
388214393ed6SStefano Zampini       if (need_benign_correction) {
3883df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
388414393ed6SStefano Zampini         PetscScalar      *marr,*sums;
388514393ed6SStefano Zampini 
388614393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
3887f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
3888df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
388914393ed6SStefano Zampini           const PetscScalar *vals;
389014393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
389114393ed6SStefano Zampini           PetscInt          n,j,nz;
389214393ed6SStefano Zampini 
3893df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3894df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
389514393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
389614393ed6SStefano Zampini             PetscInt k;
389714393ed6SStefano Zampini             sums[j] = 0.;
389814393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
389914393ed6SStefano Zampini           }
390014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
390114393ed6SStefano Zampini           for (j=0;j<n;j++) {
390214393ed6SStefano Zampini             PetscScalar val = vals[j];
390314393ed6SStefano Zampini             PetscInt k;
390414393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
390514393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
390614393ed6SStefano Zampini             }
390714393ed6SStefano Zampini           }
390814393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3909df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
391014393ed6SStefano Zampini         }
391114393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
3912f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
391314393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
391414393ed6SStefano Zampini       }
391580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
391606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
391706656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
391806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
391906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
392006656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
392106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
392206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3923d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3924019a44ceSStefano Zampini     } else {
3925d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3926d16cbb6bSStefano Zampini     }
392721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3928d16cbb6bSStefano Zampini 
392906656605SStefano Zampini     /* coarse basis functions */
393006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
393116f15bc4SStefano Zampini       PetscScalar *y;
393216f15bc4SStefano Zampini 
3933ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
393406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
393506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
393606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
393706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
393806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
393906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
394006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
394106656605SStefano Zampini 
394206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
39434f1b2e48SStefano Zampini         PetscInt j;
39444f1b2e48SStefano Zampini 
394506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
394606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
394706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
394806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
394906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
39504f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
395106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
395206656605SStefano Zampini       }
395306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
395406656605SStefano Zampini     }
395504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
395604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
395706656605SStefano Zampini   }
39585cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
395906656605SStefano Zampini 
396006656605SStefano Zampini   if (n_constraints) {
396106656605SStefano Zampini     Mat B;
396206656605SStefano Zampini 
3963ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
396406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
396580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
396606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
396706656605SStefano Zampini     if (n_vertices) {
396880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
396980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
397080677318SStefano Zampini       } else {
397180677318SStefano Zampini         Mat S_VCt;
397280677318SStefano Zampini 
3973ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3974ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
397572b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3976ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3977ffd830a3SStefano Zampini         }
397880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
397980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
398080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
398180677318SStefano Zampini       }
398206656605SStefano Zampini     }
398306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
398406656605SStefano Zampini     /* coarse basis functions */
398506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
398606656605SStefano Zampini       PetscScalar *y;
398706656605SStefano Zampini 
3988ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
398906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
399006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
399106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
399206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
399306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
399406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
399506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
39964f1b2e48SStefano Zampini         PetscInt j;
39974f1b2e48SStefano Zampini 
399806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
399906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
400006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
400106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
400206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
40034f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
400406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
400506656605SStefano Zampini       }
400606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
400706656605SStefano Zampini     }
400806656605SStefano Zampini   }
400980677318SStefano Zampini   if (n_constraints) {
401080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
401180677318SStefano Zampini   }
40124f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
401372b8c272SStefano Zampini 
401472b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
401572b8c272SStefano Zampini   if (pcbddc->benign_n) {
401672b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
401772b8c272SStefano Zampini     IS          is_dummy;
401872b8c272SStefano Zampini     PetscScalar *data;
401972b8c272SStefano Zampini     PetscInt    j;
402072b8c272SStefano Zampini 
402172b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
40227dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
402372b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
402472b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
402586c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
402672b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
402772b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
402872b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
402972b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
403072b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
403172b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
403272b8c272SStefano Zampini       }
403372b8c272SStefano Zampini     }
403472b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
403572b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
403672b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
403772b8c272SStefano Zampini   }
4038019a44ceSStefano Zampini 
403906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
40403301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4041ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4042ffd830a3SStefano Zampini     PetscScalar *marray;
404306656605SStefano Zampini 
404406656605SStefano Zampini     if (n_constraints) {
4045ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
404606656605SStefano Zampini 
4047abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
404806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4049ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
405016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
405106656605SStefano Zampini       if (n_vertices) {
4052ffd830a3SStefano Zampini         Mat S_VCT;
405306656605SStefano Zampini 
405406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4055ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
405616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
405706656605SStefano Zampini       }
4058ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
40595b782168SStefano Zampini     } else {
40605b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
406106656605SStefano Zampini     }
406216f15bc4SStefano Zampini     if (n_vertices && n_R) {
4063ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4064ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4065ffd830a3SStefano Zampini       PetscInt       n;
4066ffd830a3SStefano Zampini       PetscBool      flg_row;
406706656605SStefano Zampini 
4068ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4069af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4070ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4071ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4072ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4073ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4074ffd830a3SStefano Zampini         PetscInt j;
4075ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4076ffd830a3SStefano Zampini       }
4077ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4078ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4079ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
408006656605SStefano Zampini     }
408106656605SStefano Zampini 
4082ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4083abc8f43dSstefano_zampini     if (n_vertices) {
4084ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4085ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4086ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4087ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
408806656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
408906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
409006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
409106656605SStefano Zampini       }
4092ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4093abc8f43dSstefano_zampini     }
40945b782168SStefano Zampini     if (B_C) {
4095ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4096ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4097ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4098ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4099ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4100ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4101ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
410206656605SStefano Zampini       }
4103ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
41045b782168SStefano Zampini     }
410506656605SStefano Zampini     /* coarse basis functions */
410606656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
410706656605SStefano Zampini       PetscScalar *y;
410806656605SStefano Zampini 
4109ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
411006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
411106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
411206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
411306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
411406656605SStefano Zampini       if (i<n_vertices) {
411506656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
411606656605SStefano Zampini       }
411706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
411806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
411906656605SStefano Zampini 
412006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
412106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
412206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
412306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
412406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
412506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
412606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
412706656605SStefano Zampini       }
412806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
412906656605SStefano Zampini     }
4130ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4131ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
413206656605SStefano Zampini   }
4133a6e023c1Sstefano_zampini 
4134d62866d3SStefano Zampini   /* free memory */
413588ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
413606656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
413706656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
413806656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
413906656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4140d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4141d62866d3SStefano Zampini   if (n_vertices) {
4142d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4143d62866d3SStefano Zampini   }
4144d62866d3SStefano Zampini   if (n_constraints) {
4145d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4146d62866d3SStefano Zampini   }
414788ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
414888ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
414988ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4150d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
415188ebb749SStefano Zampini     Mat         coarse_sub_mat;
415225084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
415388ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
415488ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
415588ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
41568bec7fa6SStefano Zampini     Mat         C_B,CPHI;
41578bec7fa6SStefano Zampini     IS          is_dummy;
41588bec7fa6SStefano Zampini     Vec         mones;
415988ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
416088ebb749SStefano Zampini     PetscReal   real_value;
416188ebb749SStefano Zampini 
4162a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4163a3df083aSStefano Zampini       Mat A;
4164a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
41657dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
41667dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
41677dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
41687dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4169a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4170a3df083aSStefano Zampini     } else {
417188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
417288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
417388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
417488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4175a3df083aSStefano Zampini     }
417688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
417788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4178ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
417988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
418088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
418188ebb749SStefano Zampini     }
418288ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
418388ebb749SStefano Zampini 
418425084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41853301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
418625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4187ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
418888ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
418988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
419088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
419188ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
419288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
419388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
419488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
419588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
419688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
419788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
419888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
419988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
420088ebb749SStefano Zampini     } else {
420188ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
420288ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
420388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
420488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
420588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
420688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
420788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
420888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
420988ebb749SStefano Zampini     }
421088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
421188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
421288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4213511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
42144f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4215fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4216d12edf2fSStefano Zampini       PetscScalar *data,*data2;
42174f1b2e48SStefano Zampini       PetscInt    j;
4218d12edf2fSStefano Zampini 
42194f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
42207dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4221d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
422286c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4223d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4224d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
42254f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
42264f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4227d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
42284f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
42294f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
42304f1b2e48SStefano Zampini         }
4231d12edf2fSStefano Zampini       }
4232d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4233d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4234d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4235d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4236d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4237d12edf2fSStefano Zampini     }
4238d12edf2fSStefano Zampini #if 0
4239d12edf2fSStefano Zampini   {
4240d12edf2fSStefano Zampini     PetscViewer viewer;
4241d12edf2fSStefano Zampini     char filename[256];
4242ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4243d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4244d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4245ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4246ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4247ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4248d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
424972b8c272SStefano Zampini     if (save_change) {
425072b8c272SStefano Zampini       Mat phi_B;
425172b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
425272b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
425372b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
425472b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
425572b8c272SStefano Zampini     } else {
4256ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4257ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
425872b8c272SStefano Zampini     }
4259ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4260ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4261ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4262ffd830a3SStefano Zampini     }
4263ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4264ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4265ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4266ffd830a3SStefano Zampini     }
426772b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4268ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4269ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4270ffd830a3SStefano Zampini     }
4271d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4272d12edf2fSStefano Zampini   }
4273d12edf2fSStefano Zampini #endif
427481d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
42758bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
42761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
427706656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
42788bec7fa6SStefano Zampini 
42798bec7fa6SStefano Zampini     /* check constraints */
4280a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
42817dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
42824f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
42838bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4284a00504b5SStefano Zampini     } else {
4285a00504b5SStefano Zampini       PetscScalar *data;
4286a00504b5SStefano Zampini       Mat         tmat;
4287a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4288a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4289a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4290a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4291a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4292a00504b5SStefano Zampini     }
42938bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
42948bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
42958bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
42968bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4297bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4298ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4299bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4300bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4301bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4302bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4303bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
430488ebb749SStefano Zampini     }
43058bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
43068bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
43078bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
43088bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
430925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
431088ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
431188ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
431288ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
431388ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
431488ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
431588ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
431688ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
431788ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
431888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
431988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4320ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
432188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
432288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
432388ebb749SStefano Zampini     }
432488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
432588ebb749SStefano Zampini   }
43268629588bSStefano Zampini   /* get back data */
43278629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
432888ebb749SStefano Zampini   PetscFunctionReturn(0);
432988ebb749SStefano Zampini }
433088ebb749SStefano Zampini 
43317dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4332aa0d41d4SStefano Zampini {
4333d65f70fdSStefano Zampini   Mat            *work_mat;
4334d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4335d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4336c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4337aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4338aa0d41d4SStefano Zampini 
4339aa0d41d4SStefano Zampini   PetscFunctionBegin;
4340d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4341d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4342d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4343d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4344aa0d41d4SStefano Zampini 
4345d65f70fdSStefano Zampini   if (!rsorted) {
4346906d46d4SStefano Zampini     const PetscInt *idxs;
4347906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4348aa0d41d4SStefano Zampini 
4349d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4350d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4351d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4352d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4353aa0d41d4SStefano Zampini     }
4354d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4355d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4356d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4357d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4358aa0d41d4SStefano Zampini     }
4359d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4360d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4361d65f70fdSStefano Zampini   } else {
4362d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4363d65f70fdSStefano Zampini     isrow_s = isrow;
4364aa0d41d4SStefano Zampini   }
4365906d46d4SStefano Zampini 
4366d65f70fdSStefano Zampini   if (!csorted) {
4367d65f70fdSStefano Zampini     if (isrow == iscol) {
4368d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4369d65f70fdSStefano Zampini       iscol_s = isrow_s;
4370d65f70fdSStefano Zampini     } else {
4371d65f70fdSStefano Zampini       const PetscInt *idxs;
4372d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4373906d46d4SStefano Zampini 
4374d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4375d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4376d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4377d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4378d65f70fdSStefano Zampini       }
4379d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4380d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4381d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4382d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4383d65f70fdSStefano Zampini       }
4384d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4385d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4386d65f70fdSStefano Zampini     }
4387d65f70fdSStefano Zampini   } else {
4388d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4389d65f70fdSStefano Zampini     iscol_s = iscol;
4390d65f70fdSStefano Zampini   }
4391d65f70fdSStefano Zampini 
43927dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4393d65f70fdSStefano Zampini 
4394d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4395906d46d4SStefano Zampini     Mat      new_mat;
4396d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4397906d46d4SStefano Zampini 
4398d65f70fdSStefano Zampini     if (!rsorted) {
4399d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4400d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4401d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4402d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4403906d46d4SStefano Zampini       }
4404d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4405d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4406d65f70fdSStefano Zampini     } else {
4407d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4408906d46d4SStefano Zampini     }
4409d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4410d65f70fdSStefano Zampini 
4411d65f70fdSStefano Zampini     if (!csorted) {
4412d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4413d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4414d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4415d65f70fdSStefano Zampini       } else {
4416d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4417f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4418d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4419d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4420d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4421d65f70fdSStefano Zampini         }
4422d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4423d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4424d65f70fdSStefano Zampini       }
4425d65f70fdSStefano Zampini     } else {
4426d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4427d65f70fdSStefano Zampini     }
4428d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4429d65f70fdSStefano Zampini 
4430d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4431d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4432d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4433d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4434d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4435d65f70fdSStefano Zampini   }
4436d65f70fdSStefano Zampini 
4437d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4438d65f70fdSStefano Zampini   *B = work_mat[0];
4439d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4440d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4441d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4442d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4443d65f70fdSStefano Zampini }
4444d65f70fdSStefano Zampini 
44455e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4446aa0d41d4SStefano Zampini {
4447aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
44485e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4449022d8d2bSstefano_zampini   Mat            new_mat,lA;
44505e8657edSStefano Zampini   IS             is_local,is_global;
4451d65f70fdSStefano Zampini   PetscInt       local_size;
4452d65f70fdSStefano Zampini   PetscBool      isseqaij;
4453aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4454aa0d41d4SStefano Zampini 
4455aa0d41d4SStefano Zampini   PetscFunctionBegin;
4456aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
44575e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
44585e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4459b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4460aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
44617dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4462aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4463906d46d4SStefano Zampini 
4464906d46d4SStefano Zampini   /* check */
4465906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4466906d46d4SStefano Zampini     Vec       x,x_change;
4467906d46d4SStefano Zampini     PetscReal error;
4468906d46d4SStefano Zampini 
44695e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4470906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
44715e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4472e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4473e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4474d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
447588428137SStefano Zampini     if (!pcbddc->change_interior) {
447688428137SStefano Zampini       const PetscScalar *x,*y,*v;
447788428137SStefano Zampini       PetscReal         lerror = 0.;
447888428137SStefano Zampini       PetscInt          i;
447988428137SStefano Zampini 
448088428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
448188428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
448288428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
448388428137SStefano Zampini       for (i=0;i<local_size;i++)
448488428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
448588428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
448688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
448788428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
448888428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
448988428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4490637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4491637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4492637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4493637e8532SStefano Zampini         } else {
4494637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4495637e8532SStefano Zampini         }
4496637e8532SStefano Zampini       }
449788428137SStefano Zampini     }
4498e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4499e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4500906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4501906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4502637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4503637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4504637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4505637e8532SStefano Zampini       } else {
4506637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4507637e8532SStefano Zampini       }
4508637e8532SStefano Zampini     }
4509906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4510906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4511906d46d4SStefano Zampini   }
4512906d46d4SStefano Zampini 
4513022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4514022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4515022d8d2bSstefano_zampini 
451622d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
45179b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
451822d5777bSStefano Zampini   if (isseqaij) {
4519a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4520a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4521022d8d2bSstefano_zampini     if (lA) {
4522022d8d2bSstefano_zampini       Mat work;
4523022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4524022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4525022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4526022d8d2bSstefano_zampini     }
4527aa0d41d4SStefano Zampini   } else {
4528a00504b5SStefano Zampini     Mat work_mat;
45291cf9b237SStefano Zampini 
4530a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4531aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4532a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
45331d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4534022d8d2bSstefano_zampini     if (lA) {
4535022d8d2bSstefano_zampini       Mat work;
4536022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4537022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4538022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4539022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4540022d8d2bSstefano_zampini     }
4541aa0d41d4SStefano Zampini   }
45423301b35fSStefano Zampini   if (matis->A->symmetric_set) {
45433301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4544e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
45453301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4546e496cd5dSStefano Zampini #endif
45473301b35fSStefano Zampini   }
4548d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4549aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4550aa0d41d4SStefano Zampini }
4551aa0d41d4SStefano Zampini 
45528ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4553a64d13efSStefano Zampini {
4554a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4555a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4556d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
455753892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
45583a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
45593a50541eSStefano Zampini   PetscInt        vbs,bs;
45606816873aSStefano Zampini   PetscBT         bitmask=NULL;
4561a64d13efSStefano Zampini   PetscErrorCode  ierr;
4562a64d13efSStefano Zampini 
4563a64d13efSStefano Zampini   PetscFunctionBegin;
4564b23d619eSStefano Zampini   /*
4565b23d619eSStefano Zampini     No need to setup local scatters if
4566b23d619eSStefano Zampini       - primal space is unchanged
4567b23d619eSStefano Zampini         AND
4568b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4569b23d619eSStefano Zampini         AND
4570b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4571b23d619eSStefano Zampini   */
4572b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4573f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4574f4ddd8eeSStefano Zampini   }
4575f4ddd8eeSStefano Zampini   /* destroy old objects */
4576f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4577f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4578f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4579a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4580b371cd4fSStefano Zampini   n_B = pcis->n_B;
4581b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4582b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
45833a50541eSStefano Zampini 
4584a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
45856816873aSStefano Zampini 
458653892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4587b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4588854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4589a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4590a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
45910e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4592a64d13efSStefano Zampini     }
4593a64d13efSStefano Zampini 
4594a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
45954641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
45966816873aSStefano Zampini         idx_R_local[n_R++] = i;
4597a64d13efSStefano Zampini       }
4598a64d13efSStefano Zampini     }
4599df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4600df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
46016816873aSStefano Zampini 
4602df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4603df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
46046816873aSStefano Zampini   }
46053a50541eSStefano Zampini 
46063a50541eSStefano Zampini   /* Block code */
46073a50541eSStefano Zampini   vbs = 1;
46083a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
46093a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
46103a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
46113a50541eSStefano Zampini     PetscInt  *vary;
4612b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4613785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
46143a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4615d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4616d3df7717SStefano Zampini       /* it is ok to check this way since local_primal_ref_node are always sorted by local numbering and idx_R_local is obtained as a complement */
46170e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4618d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
46193a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
46203a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
46213a50541eSStefano Zampini           break;
46223a50541eSStefano Zampini         }
46233a50541eSStefano Zampini       }
4624d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4625d3df7717SStefano Zampini     } else {
4626d3df7717SStefano Zampini       /* Verify directly the R set */
4627d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4628d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4629d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4630d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4631d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4632d3df7717SStefano Zampini             break;
4633d3df7717SStefano Zampini           }
4634d3df7717SStefano Zampini         }
4635d3df7717SStefano Zampini       }
4636d3df7717SStefano Zampini     }
46373a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
46383a50541eSStefano Zampini       vbs = bs;
46393a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
46403a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
46413a50541eSStefano Zampini       }
46423a50541eSStefano Zampini     }
46433a50541eSStefano Zampini   }
46443a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4645b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4646df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
464753892102SStefano Zampini 
4648df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4649df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
465053892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4651df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
465253892102SStefano Zampini   } else {
46533a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
465453892102SStefano Zampini   }
4655a64d13efSStefano Zampini 
4656a64d13efSStefano Zampini   /* print some info if requested */
4657a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4658a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4659a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46601575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4661a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4662a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
46634f1b2e48SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices-pcbddc->benign_n,pcbddc->local_primal_size);CHKERRQ(ierr);
4664a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4665a64d13efSStefano Zampini   }
4666a64d13efSStefano Zampini 
4667a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4668b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
46696816873aSStefano Zampini     IS       is_aux1,is_aux2;
46706816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
46716816873aSStefano Zampini 
46723a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4673854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4674854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4675a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
46764641a718SStefano Zampini     for (i=0; i<n_D; i++) {
46774641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
46784641a718SStefano Zampini     }
4679a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4680a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
46814641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
46824641a718SStefano Zampini         aux_array1[j++] = i;
4683a64d13efSStefano Zampini       }
4684a64d13efSStefano Zampini     }
4685a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4686a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4687a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
46884641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
46894641a718SStefano Zampini         aux_array2[j++] = i;
4690a64d13efSStefano Zampini       }
4691a64d13efSStefano Zampini     }
4692a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4693a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4694a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4695a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4696a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4697a64d13efSStefano Zampini 
46988eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4699785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4700a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
47014641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
47024641a718SStefano Zampini           aux_array1[j++] = i;
4703a64d13efSStefano Zampini         }
4704a64d13efSStefano Zampini       }
4705a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4706a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4707a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4708a64d13efSStefano Zampini     }
47094641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
47103a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4711d62866d3SStefano Zampini   } else {
4712df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
47136816873aSStefano Zampini     IS                 tis;
47146816873aSStefano Zampini     PetscInt           schur_size;
47156816873aSStefano Zampini 
4716df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
47176816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4718df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
47196816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
47206816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
47216816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
47226816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
47236816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4724d62866d3SStefano Zampini     }
4725d62866d3SStefano Zampini   }
4726a64d13efSStefano Zampini   PetscFunctionReturn(0);
4727a64d13efSStefano Zampini }
4728a64d13efSStefano Zampini 
4729304d26faSStefano Zampini 
4730684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4731304d26faSStefano Zampini {
4732304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4733304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4734304d26faSStefano Zampini   PC             pc_temp;
4735304d26faSStefano Zampini   Mat            A_RR;
4736f4ddd8eeSStefano Zampini   MatReuse       reuse;
4737304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4738304d26faSStefano Zampini   PetscReal      value;
473904708bb6SStefano Zampini   PetscInt       n_D,n_R;
4740c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4741304d26faSStefano Zampini   PetscErrorCode ierr;
4742e604994aSStefano Zampini   /* prefixes stuff */
4743312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4744e604994aSStefano Zampini   size_t         len;
4745304d26faSStefano Zampini 
4746304d26faSStefano Zampini   PetscFunctionBegin;
4747304d26faSStefano Zampini 
4748e604994aSStefano Zampini   /* compute prefixes */
4749e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4750e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4751e604994aSStefano Zampini   if (!pcbddc->current_level) {
4752e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4753e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4754e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4755e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4756e604994aSStefano Zampini   } else {
4757e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4758312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4759e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4760e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4761312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4762312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
476334d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
476434d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4765e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4766e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4767e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4768e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4769e604994aSStefano Zampini   }
4770e604994aSStefano Zampini 
4771304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4772684f6988SStefano Zampini   if (dirichlet) {
4773d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4774450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
47759a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4776450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4777a3df083aSStefano Zampini         Mat    A_IIn;
4778a3df083aSStefano Zampini 
4779a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4780a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4781a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4782a3df083aSStefano Zampini       }
4783450f8f5eSStefano Zampini     }
47843301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
47853301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4786964fefecSStefano Zampini     }
4787ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4788964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4789304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4790304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4791304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4792304d26faSStefano Zampini       /* default */
4793304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4794e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
47959577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4796304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
47979577ea80SStefano Zampini       if (issbaij) {
47989577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
47999577ea80SStefano Zampini       } else {
4800304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
48019577ea80SStefano Zampini       }
4802304d26faSStefano Zampini       /* Allow user's customization */
4803304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4804304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4805304d26faSStefano Zampini     }
4806d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4807b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4808df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4809d62866d3SStefano Zampini 
4810df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4811d5574798SStefano Zampini     }
4812304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4813304d26faSStefano Zampini     if (!n_D) {
4814304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4815304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4816304d26faSStefano Zampini     }
4817304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4818304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4819304d26faSStefano Zampini     /* set ksp_D into pcis data */
4820304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4821304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4822304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4823684f6988SStefano Zampini   }
4824304d26faSStefano Zampini 
4825304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4826684f6988SStefano Zampini   A_RR = 0;
4827684f6988SStefano Zampini   if (neumann) {
4828d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
482904708bb6SStefano Zampini     PetscInt        ibs,mbs;
483004708bb6SStefano Zampini     PetscBool       issbaij;
483104708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4832f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
48338ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4834f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4835f4ddd8eeSStefano Zampini       PetscInt nn_R;
483681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4837f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4838f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4839f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4840f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4841f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4842f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4843f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4844727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4845f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4846f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4847f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4848f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4849f4ddd8eeSStefano Zampini         }
4850f4ddd8eeSStefano Zampini       }
4851f4ddd8eeSStefano Zampini       /* last check */
4852d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4853f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4854f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4855f4ddd8eeSStefano Zampini       }
4856f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4857f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4858f4ddd8eeSStefano Zampini     }
4859a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4860af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4861af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
486204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
486304708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
486404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
486504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
486604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4867af732b37SStefano Zampini       } else {
4868511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
48696816873aSStefano Zampini       }
487004708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
487104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
487204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
487304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
487404708bb6SStefano Zampini       } else {
4875511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
487604708bb6SStefano Zampini       }
487704708bb6SStefano Zampini     }
4878a00504b5SStefano Zampini     /* extract A_RR */
4879b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4880a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4881a00504b5SStefano Zampini 
4882a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
488316e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4884a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
488516e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
488616e386b8SStefano Zampini         } else {
48877dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4888a00504b5SStefano Zampini         }
4889a00504b5SStefano Zampini       } else {
4890a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4891a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4892a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4893a00504b5SStefano Zampini       }
4894a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
48957dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
489616e386b8SStefano Zampini     }
48973301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
48983301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
48996816873aSStefano Zampini     }
4900f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4901304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4902304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4903304d26faSStefano Zampini       /* default */
4904304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4905e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4906304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
49079577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
49089577ea80SStefano Zampini       if (issbaij) {
49099577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
49109577ea80SStefano Zampini       } else {
4911304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
49129577ea80SStefano Zampini       }
4913304d26faSStefano Zampini       /* Allow user's customization */
4914304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4915304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4916304d26faSStefano Zampini     }
4917304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4918304d26faSStefano Zampini     if (!n_R) {
4919304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4920304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4921304d26faSStefano Zampini     }
49225cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4923df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4924111315fdSstefano_zampini     if (sub_schurs && sub_schurs->reuse_solver && sub_schurs->A == pcbddc->local_mat) {
4925df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4926d62866d3SStefano Zampini 
4927df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4928d62866d3SStefano Zampini     }
4929304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4930304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4931684f6988SStefano Zampini   }
4932304d26faSStefano Zampini 
4933684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4934684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
49351575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4936684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4937684f6988SStefano Zampini   }
4938c7017625SStefano Zampini 
4939c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4940c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4941c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4942c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4943c7017625SStefano Zampini   }
4944c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4945c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4946c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4947c7017625SStefano Zampini   }
4948c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4949c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4950c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4951c7017625SStefano Zampini   }
4952c7017625SStefano Zampini 
4953c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4954c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4955684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
49560fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
49570fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
49580fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
49590fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
49600fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4961e604994aSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_D))->prefix,value);CHKERRQ(ierr);
4962c7017625SStefano Zampini       if (check_corr[0]) {
4963c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4964c7017625SStefano Zampini       }
4965304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4966304d26faSStefano Zampini     }
4967684f6988SStefano Zampini     if (neumann) { /* Neumann */
49680fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
49690fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
49700fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
49710fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
49720fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4973e604994aSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_R))->prefix,value);CHKERRQ(ierr);
4974c7017625SStefano Zampini       if (check_corr[1]) {
4975c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4976c7017625SStefano Zampini       }
4977304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4978304d26faSStefano Zampini     }
4979684f6988SStefano Zampini   }
49805cbda25cSStefano Zampini   /* free Neumann problem's matrix */
49815cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4982304d26faSStefano Zampini   PetscFunctionReturn(0);
4983304d26faSStefano Zampini }
4984304d26faSStefano Zampini 
498580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4986674ae819SStefano Zampini {
4987674ae819SStefano Zampini   PetscErrorCode  ierr;
4988674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4989be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4990b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4991674ae819SStefano Zampini 
4992674ae819SStefano Zampini   PetscFunctionBegin;
4993b334f244SStefano Zampini   if (!reuse_solver) {
499480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
499520c7b377SStefano Zampini   }
499680677318SStefano Zampini   if (!pcbddc->switch_static) {
499780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
499880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
499980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
500020c7b377SStefano Zampini     }
5001b334f244SStefano Zampini     if (!reuse_solver) {
500280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
500380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
500420c7b377SStefano Zampini     } else {
5005df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5006be83ff47SStefano Zampini 
5007df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5008df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
500920c7b377SStefano Zampini     }
5010be83ff47SStefano Zampini   } else {
501180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
501280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
501380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
501480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
501580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
501680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
501780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
501880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
501980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5020674ae819SStefano Zampini     }
5021674ae819SStefano Zampini   }
5022b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
502380677318SStefano Zampini     if (applytranspose) {
502480677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
502580677318SStefano Zampini     } else {
502680677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
502780677318SStefano Zampini     }
5028be83ff47SStefano Zampini   } else {
5029df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5030be83ff47SStefano Zampini 
5031be83ff47SStefano Zampini     if (applytranspose) {
5032df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5033be83ff47SStefano Zampini     } else {
5034df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5035be83ff47SStefano Zampini     }
5036be83ff47SStefano Zampini   }
503780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
503880677318SStefano Zampini   if (!pcbddc->switch_static) {
5039b334f244SStefano Zampini     if (!reuse_solver) {
504080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
504180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5042be83ff47SStefano Zampini     } else {
5043df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5044be83ff47SStefano Zampini 
5045df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5046df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5047be83ff47SStefano Zampini     }
504880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
504980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
505080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
505180677318SStefano Zampini     }
505280677318SStefano Zampini   } else {
505380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
505480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
505580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
505680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
505780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
505880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
505980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
506080677318SStefano Zampini     }
506180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
506280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
506380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
506480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5065674ae819SStefano Zampini   }
5066674ae819SStefano Zampini   PetscFunctionReturn(0);
5067674ae819SStefano Zampini }
5068674ae819SStefano Zampini 
5069dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5070dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5071674ae819SStefano Zampini {
5072674ae819SStefano Zampini   PetscErrorCode ierr;
5073674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5074674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5075674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5076674ae819SStefano Zampini 
5077674ae819SStefano Zampini   PetscFunctionBegin;
5078dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
50794fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5080dc359a40SStefano Zampini     if (applytranspose) {
5081674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
50828eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5083dc359a40SStefano Zampini     } else {
5084674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5085674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
508615aaf578SStefano Zampini     }
50874fee134fSStefano Zampini   } else {
50884fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
50894fee134fSStefano Zampini   }
5090efc2fbd9SStefano Zampini 
5091efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
50924f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5093efc2fbd9SStefano Zampini     PetscScalar *array;
50944f1b2e48SStefano Zampini     PetscInt    j;
5095efc2fbd9SStefano Zampini 
5096efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
50974f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5098efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5099efc2fbd9SStefano Zampini   }
5100efc2fbd9SStefano Zampini 
510112edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
510212edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
510312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
510412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
510512edc857SStefano Zampini 
51069f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
510712edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
510851694757SStefano Zampini     Mat          coarse_mat;
5109964fefecSStefano Zampini     Vec          rhs,sol;
511051694757SStefano Zampini     MatNullSpace nullsp;
511127b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5112964fefecSStefano Zampini 
511327b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
511427b6a85dSStefano Zampini       PC        coarse_pc;
511527b6a85dSStefano Zampini 
511627b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
511727b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
511827b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
511927b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
512027b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
512127b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
51223bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
512327b6a85dSStefano Zampini       }
512427b6a85dSStefano Zampini     }
5125964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5126964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
512751694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
512851694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
512951694757SStefano Zampini     if (nullsp) {
513051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
513151694757SStefano Zampini     }
513212edc857SStefano Zampini     if (applytranspose) {
51339a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5134964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
51352701bc32SStefano Zampini     } else {
51361f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
51372701bc32SStefano Zampini         PC        coarse_pc;
51382701bc32SStefano Zampini 
51392701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
51402701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
51413e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
51422701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
514312edc857SStefano Zampini       } else {
5144964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
514512edc857SStefano Zampini       }
51462701bc32SStefano Zampini     }
51471d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
514827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
514927b6a85dSStefano Zampini       PC        coarse_pc;
515027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
515127b6a85dSStefano Zampini 
515227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
515327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
515427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
51553bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
515627b6a85dSStefano Zampini     }
515751694757SStefano Zampini     if (nullsp) {
515851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
515951694757SStefano Zampini     }
516012edc857SStefano Zampini   }
5161674ae819SStefano Zampini 
5162674ae819SStefano Zampini   /* Local solution on R nodes */
51634fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
516480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
51659f00e9b4SStefano Zampini   }
51669f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
51679f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
516812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5169674ae819SStefano Zampini 
51704fee134fSStefano Zampini   /* Sum contributions from the two levels */
51714fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5172dc359a40SStefano Zampini     if (applytranspose) {
5173dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5174dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5175dc359a40SStefano Zampini     } else {
5176674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
51778eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5178dc359a40SStefano Zampini     }
5179efc2fbd9SStefano Zampini     /* store p0 */
51804f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5181efc2fbd9SStefano Zampini       PetscScalar *array;
51824f1b2e48SStefano Zampini       PetscInt    j;
5183efc2fbd9SStefano Zampini 
5184efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
51854f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5186efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5187efc2fbd9SStefano Zampini     }
51884fee134fSStefano Zampini   } else { /* expand the coarse solution */
51894fee134fSStefano Zampini     if (applytranspose) {
51904fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
51914fee134fSStefano Zampini     } else {
51924fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
51934fee134fSStefano Zampini     }
51944fee134fSStefano Zampini   }
5195674ae819SStefano Zampini   PetscFunctionReturn(0);
5196674ae819SStefano Zampini }
5197674ae819SStefano Zampini 
519812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5199674ae819SStefano Zampini {
5200674ae819SStefano Zampini   PetscErrorCode ierr;
5201674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
520258da7f69SStefano Zampini   PetscScalar    *array;
520312edc857SStefano Zampini   Vec            from,to;
5204674ae819SStefano Zampini 
5205674ae819SStefano Zampini   PetscFunctionBegin;
520612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
520712edc857SStefano Zampini     from = pcbddc->coarse_vec;
520812edc857SStefano Zampini     to = pcbddc->vec1_P;
520912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
521012edc857SStefano Zampini       Vec tvec;
521158da7f69SStefano Zampini 
521258da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
521358da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
521412edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
521558da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
521658da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
521758da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
521812edc857SStefano Zampini     }
521912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
522012edc857SStefano Zampini     from = pcbddc->vec1_P;
522112edc857SStefano Zampini     to = pcbddc->coarse_vec;
522212edc857SStefano Zampini   }
522312edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5224674ae819SStefano Zampini   PetscFunctionReturn(0);
5225674ae819SStefano Zampini }
5226674ae819SStefano Zampini 
522712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5228674ae819SStefano Zampini {
5229674ae819SStefano Zampini   PetscErrorCode ierr;
5230674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
523158da7f69SStefano Zampini   PetscScalar    *array;
523212edc857SStefano Zampini   Vec            from,to;
5233674ae819SStefano Zampini 
5234674ae819SStefano Zampini   PetscFunctionBegin;
523512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
523612edc857SStefano Zampini     from = pcbddc->coarse_vec;
523712edc857SStefano Zampini     to = pcbddc->vec1_P;
523812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
523912edc857SStefano Zampini     from = pcbddc->vec1_P;
524012edc857SStefano Zampini     to = pcbddc->coarse_vec;
524112edc857SStefano Zampini   }
524212edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
524312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
524412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
524512edc857SStefano Zampini       Vec tvec;
524658da7f69SStefano Zampini 
524712edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
524858da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
524958da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
525058da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
525158da7f69SStefano Zampini     }
525258da7f69SStefano Zampini   } else {
525358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
525458da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
525512edc857SStefano Zampini     }
525612edc857SStefano Zampini   }
5257674ae819SStefano Zampini   PetscFunctionReturn(0);
5258674ae819SStefano Zampini }
5259674ae819SStefano Zampini 
5260984c4197SStefano Zampini /* uncomment for testing purposes */
5261984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5262674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5263674ae819SStefano Zampini {
5264674ae819SStefano Zampini   PetscErrorCode    ierr;
5265674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5266674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5267674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5268984c4197SStefano Zampini   /* one and zero */
5269984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5270984c4197SStefano Zampini   /* space to store constraints and their local indices */
52719162d606SStefano Zampini   PetscScalar       *constraints_data;
52729162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
52739162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
52749162d606SStefano Zampini   PetscInt          *constraints_n;
5275984c4197SStefano Zampini   /* iterators */
5276b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5277984c4197SStefano Zampini   /* BLAS integers */
5278e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5279e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5280c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5281727cdba6SStefano Zampini   /* reuse */
52820e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
52830e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5284984c4197SStefano Zampini   /* change of basis */
5285b3d85658SStefano Zampini   PetscBool         qr_needed;
52869162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5287984c4197SStefano Zampini   /* auxiliary stuff */
528864efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
52898a0068c3SStefano Zampini   PetscInt          ncc;
5290984c4197SStefano Zampini   /* some quantities */
529145a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5292a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
5293984c4197SStefano Zampini 
5294674ae819SStefano Zampini   PetscFunctionBegin;
52958e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
52968e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
52978e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
529816909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5299088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5300088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
53010e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
53020e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
53030e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
53040e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
53050e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5306088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5307cf5a6209SStefano Zampini 
5308cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
53099162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5310cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5311cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5312cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5313cf5a6209SStefano Zampini     PetscScalar  *array;
5314cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5315cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5316674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5317b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5318674ae819SStefano Zampini     PetscScalar  *work;
5319674ae819SStefano Zampini     PetscReal    *singular_vals;
5320674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5321674ae819SStefano Zampini     PetscReal    *rwork;
5322674ae819SStefano Zampini #endif
5323674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5324674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5325674ae819SStefano Zampini #else
5326964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5327964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5328674ae819SStefano Zampini #endif
5329674ae819SStefano Zampini 
5330674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5331d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5332e4d548c7SStefano Zampini     /* print some info */
53335c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5334e4d548c7SStefano Zampini       PetscInt nv;
5335e4d548c7SStefano Zampini 
5336c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5337e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5338e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5339e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5340e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5341e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5342e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5343e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5344e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5345e4d548c7SStefano Zampini     }
5346e4d548c7SStefano Zampini 
5347d06fc5fdSStefano Zampini     /* free unneeded index sets */
5348d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5349d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5350674ae819SStefano Zampini     }
5351d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5352d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5353d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5354d06fc5fdSStefano Zampini       }
5355d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5356d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5357d06fc5fdSStefano Zampini     }
5358d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5359d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5360d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5361d06fc5fdSStefano Zampini       }
5362d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5363d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5364d06fc5fdSStefano Zampini     }
536570022509SStefano Zampini 
5366674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5367674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5368674ae819SStefano Zampini     if (nearnullsp) {
5369674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5370f4ddd8eeSStefano Zampini       /* remove any stored info */
5371f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5372f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5373f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5374f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5375f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5376473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5377f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5378f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5379f4ddd8eeSStefano Zampini       }
5380984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5381984c4197SStefano Zampini       nnsp_size = 0;
5382674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5383674ae819SStefano Zampini     }
5384984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5385984c4197SStefano Zampini     max_constraints = nnsp_size;
5386984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5387984c4197SStefano Zampini 
5388674ae819SStefano Zampini     /*
5389674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
53909162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
53919162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
53929162d606SStefano Zampini          There can be multiple constraints per connected component
5393674ae819SStefano Zampini                                                                                                                                                            */
5394674ae819SStefano Zampini     n_vertices = 0;
5395674ae819SStefano Zampini     if (ISForVertices) {
5396674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5397674ae819SStefano Zampini     }
53989162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
53999162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
54009162d606SStefano Zampini 
54019162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
54029162d606SStefano Zampini     total_counts *= max_constraints;
5403674ae819SStefano Zampini     total_counts += n_vertices;
54044641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
54059162d606SStefano Zampini 
5406674ae819SStefano Zampini     total_counts = 0;
5407674ae819SStefano Zampini     max_size_of_constraint = 0;
5408674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
54099162d606SStefano Zampini       IS used_is;
5410674ae819SStefano Zampini       if (i<n_ISForEdges) {
54119162d606SStefano Zampini         used_is = ISForEdges[i];
5412674ae819SStefano Zampini       } else {
54139162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5414674ae819SStefano Zampini       }
54159162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5416674ae819SStefano Zampini       total_counts += j;
5417674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5418674ae819SStefano Zampini     }
54199162d606SStefano Zampini     ierr = PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B);CHKERRQ(ierr);
54209162d606SStefano Zampini 
5421984c4197SStefano Zampini     /* get local part of global near null space vectors */
5422785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5423984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5424984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5425e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5426e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5427984c4197SStefano Zampini     }
5428674ae819SStefano Zampini 
5429242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5430242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5431a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5432242a89d7SStefano Zampini 
5433984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5434a773dcb8SStefano Zampini     if (!skip_lapack) {
5435674ae819SStefano Zampini       PetscScalar temp_work;
5436911cabfeSStefano Zampini 
5437674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5438984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5439785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5440785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5441785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5442674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5443785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5444674ae819SStefano Zampini #endif
5445674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5446c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5447c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5448674ae819SStefano Zampini       lwork = -1;
5449674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5450674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5451c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5452674ae819SStefano Zampini #else
5453c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5454674ae819SStefano Zampini #endif
5455674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5456984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5457674ae819SStefano Zampini #else /* on missing GESVD */
5458674ae819SStefano Zampini       /* SVD */
5459674ae819SStefano Zampini       PetscInt max_n,min_n;
5460674ae819SStefano Zampini       max_n = max_size_of_constraint;
5461984c4197SStefano Zampini       min_n = max_constraints;
5462984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5463674ae819SStefano Zampini         min_n = max_size_of_constraint;
5464984c4197SStefano Zampini         max_n = max_constraints;
5465674ae819SStefano Zampini       }
5466785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5467674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5468785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5469674ae819SStefano Zampini #endif
5470674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5471674ae819SStefano Zampini       lwork = -1;
5472e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5473e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5474b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5475674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5476674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
54779162d606SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr));
5478674ae819SStefano Zampini #else
54799162d606SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr));
5480674ae819SStefano Zampini #endif
5481674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5482984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5483984c4197SStefano Zampini #endif /* on missing GESVD */
5484674ae819SStefano Zampini       /* Allocate optimal workspace */
5485674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5486854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5487674ae819SStefano Zampini     }
5488674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5489674ae819SStefano Zampini     total_counts = 0;
54909162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
54919162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5492674ae819SStefano Zampini     /* vertices */
54939162d606SStefano Zampini     if (n_vertices) {
5494674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
54959162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5496674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
54979162d606SStefano Zampini         constraints_n[total_counts] = 1;
54989162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
54999162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
55009162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5501674ae819SStefano Zampini         total_counts++;
5502674ae819SStefano Zampini       }
5503674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5504674ae819SStefano Zampini       n_vertices = total_counts;
5505674ae819SStefano Zampini     }
5506984c4197SStefano Zampini 
5507674ae819SStefano Zampini     /* edges and faces */
55089162d606SStefano Zampini     total_counts_cc = total_counts;
5509911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
55109162d606SStefano Zampini       IS        used_is;
55119162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
55129162d606SStefano Zampini 
5513911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
55149162d606SStefano Zampini         used_is = ISForEdges[ncc];
5515984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5516674ae819SStefano Zampini       } else {
55179162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5518984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5519674ae819SStefano Zampini       }
5520674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
55219162d606SStefano Zampini 
55229162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
55239162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5524984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5525984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5526674ae819SStefano Zampini       if (nnsp_has_cnst) {
55275b08dc53SStefano Zampini         PetscScalar quad_value;
55289162d606SStefano Zampini 
55299162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
55309162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
55319162d606SStefano Zampini 
5532a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5533674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5534a773dcb8SStefano Zampini         } else {
5535a773dcb8SStefano Zampini           quad_value = 1.0;
5536a773dcb8SStefano Zampini         }
5537674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
55389162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5539674ae819SStefano Zampini         }
55409162d606SStefano Zampini         temp_constraints++;
5541674ae819SStefano Zampini         total_counts++;
5542674ae819SStefano Zampini       }
5543674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5544984c4197SStefano Zampini         PetscReal real_value;
55459162d606SStefano Zampini         PetscScalar *ptr_to_data;
55469162d606SStefano Zampini 
5547984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
55489162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5549674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
55509162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5551674ae819SStefano Zampini         }
5552984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5553984c4197SStefano Zampini         /* check if array is null on the connected component */
5554e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55559162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
55565b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5557674ae819SStefano Zampini           temp_constraints++;
5558674ae819SStefano Zampini           total_counts++;
55599162d606SStefano Zampini           if (!idxs_copied) {
55609162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
55619162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5562674ae819SStefano Zampini           }
5563674ae819SStefano Zampini         }
55649162d606SStefano Zampini       }
55659162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
556645a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5567eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5568a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
55699162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
55709162d606SStefano Zampini 
55719162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5572a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55739162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5574a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
55759162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5576a773dcb8SStefano Zampini         } else { /* perform SVD */
5577984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
55789162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5579674ae819SStefano Zampini 
5580674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5581984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5582984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5583984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5584984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5585984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5586984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5587984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5588984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5589674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5590e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5591984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5592674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5593674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
55949162d606SStefano Zampini               PetscStackCallBLAS("BLASdot",correlation_mat[j*temp_constraints+k] = BLASdot_(&Blas_N,ptr_to_data+k*size_of_constraint,&Blas_one,ptr_to_data+j*size_of_constraint,&Blas_one));
5595674ae819SStefano Zampini             }
5596674ae819SStefano Zampini           }
5597e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5598e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5599e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5600674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5601c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5602674ae819SStefano Zampini #else
5603c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5604674ae819SStefano Zampini #endif
5605674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5606984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5607984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5608674ae819SStefano Zampini           j = 0;
5609984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5610674ae819SStefano Zampini           total_counts = total_counts-j;
561145a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5612e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5613c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5614c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5615c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5616c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5617c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5618c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5619674ae819SStefano Zampini           if (j<temp_constraints) {
5620984c4197SStefano Zampini             PetscInt ii;
5621984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5622674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
56239162d606SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,ptr_to_data,&Blas_LDA,correlation_mat,&Blas_LDB,&zero,temp_basis,&Blas_LDC));
5624674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5625984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5626674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
56279162d606SStefano Zampini                 ptr_to_data[k*size_of_constraint+ii] = singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii];
5628674ae819SStefano Zampini               }
5629674ae819SStefano Zampini             }
5630674ae819SStefano Zampini           }
5631674ae819SStefano Zampini #else  /* on missing GESVD */
5632e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5633e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5634b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5635674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5636674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
56379162d606SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr));
5638674ae819SStefano Zampini #else
56399162d606SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr));
5640674ae819SStefano Zampini #endif
5641984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5642674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5643984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5644e310c8b4SStefano Zampini           k = temp_constraints;
5645e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5646674ae819SStefano Zampini           j = 0;
5647e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
564845a1bb75SStefano Zampini           valid_constraints = k-j;
5649911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5650984c4197SStefano Zampini #endif /* on missing GESVD */
5651674ae819SStefano Zampini         }
5652a773dcb8SStefano Zampini       }
56539162d606SStefano Zampini       /* update pointers information */
56549162d606SStefano Zampini       if (valid_constraints) {
56559162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
56569162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
56579162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
56589162d606SStefano Zampini         /* set change_of_basis flag */
565945a1bb75SStefano Zampini         if (boolforchange) {
5660b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
56619162d606SStefano Zampini         }
5662b3d85658SStefano Zampini         total_counts_cc++;
566345a1bb75SStefano Zampini       }
566445a1bb75SStefano Zampini     }
5665984c4197SStefano Zampini     /* free workspace */
56668f1c130eSStefano Zampini     if (!skip_lapack) {
5667984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5668984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5669984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5670984c4197SStefano Zampini #endif
5671984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5672984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5673984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5674984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5675984c4197SStefano Zampini #endif
5676984c4197SStefano Zampini     }
5677984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5678984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5679984c4197SStefano Zampini     }
5680984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5681cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5682cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5683cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5684cf5a6209SStefano Zampini     }
5685cf5a6209SStefano Zampini     if (n_ISForFaces) {
5686cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5687cf5a6209SStefano Zampini     }
5688cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5689cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5690cf5a6209SStefano Zampini     }
5691cf5a6209SStefano Zampini     if (n_ISForEdges) {
5692cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5693cf5a6209SStefano Zampini     }
5694cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
569508122e43SStefano Zampini   } else {
569608122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5697984c4197SStefano Zampini 
569808122e43SStefano Zampini     total_counts = 0;
569908122e43SStefano Zampini     n_vertices = 0;
5700d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5701d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
570208122e43SStefano Zampini     }
570308122e43SStefano Zampini     max_constraints = 0;
57049162d606SStefano Zampini     total_counts_cc = 0;
570508122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
570608122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
57079162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
570808122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
570908122e43SStefano Zampini     }
57109162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
57119162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
57129162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
57139162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
571474d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
57159162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
57169162d606SStefano Zampini     total_counts_cc = 0;
57179162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
57189162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
57199162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
572008122e43SStefano Zampini       }
572108122e43SStefano Zampini     }
57229162d606SStefano Zampini #if 0
57239162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
57249162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
57259162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
57269162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
57279162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
57289162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
57299162d606SStefano Zampini       }
57309162d606SStefano Zampini       printf("\n");
57319162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
57329162d606SStefano Zampini     }
57331b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
57348bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
57351b968477SStefano Zampini     }
57361b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
57378bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] sub %d, edge %d, n %d\n",PetscGlobalRank,i,(PetscBool)PetscBTLookup(sub_schurs->is_edge,i),pcbddc->adaptive_constraints_n[i+n_vertices]);
57381b968477SStefano Zampini     }
573908122e43SStefano Zampini #endif
574008122e43SStefano Zampini 
57418bec7fa6SStefano Zampini     max_size_of_constraint = 0;
57429162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]);
57439162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
574408122e43SStefano Zampini     /* Change of basis */
5745b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
574608122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
574708122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
574808122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5749b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
575008122e43SStefano Zampini         }
575108122e43SStefano Zampini       }
575208122e43SStefano Zampini     }
575308122e43SStefano Zampini   }
5754984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
57554f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
575608122e43SStefano Zampini 
57579162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
57589162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
5759eee23b56SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
5760674ae819SStefano Zampini 
5761674ae819SStefano Zampini   /* Create constraint matrix */
5762674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
576316f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5764984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5765984c4197SStefano Zampini 
5766984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5767a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5768a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
576974d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5770984c4197SStefano Zampini   total_primal_vertices=0;
5771b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
57729162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
57739162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
577472b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
57759162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5776b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
577764efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
57789162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
57799162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5780a717540cSStefano Zampini       }
5781b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
578291af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5783a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5784a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5785a717540cSStefano Zampini       }
5786fa434743SStefano Zampini     } else {
5787b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5788fa434743SStefano Zampini     }
5789a717540cSStefano Zampini   }
5790b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5791b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5792674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
579370022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
57944f1b2e48SStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
57950e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
57960e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5797984c4197SStefano Zampini 
5798984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
579974d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5800785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5801984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
580274d5cdf7SStefano Zampini 
5803984c4197SStefano Zampini   j = total_primal_vertices;
580474d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5805b3d85658SStefano Zampini   cum = total_primal_vertices;
58069162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
58074641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5808b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5809b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5810b3d85658SStefano Zampini       cum++;
58119162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
581274d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
581374d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
581474d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
581574d5cdf7SStefano Zampini       }
58169162d606SStefano Zampini       j += constraints_n[i];
5817674ae819SStefano Zampini     }
5818674ae819SStefano Zampini   }
5819674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5820674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5821088faed8SStefano Zampini 
5822674ae819SStefano Zampini   /* set values in constraint matrix */
5823984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
58240e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5825674ae819SStefano Zampini   }
5826984c4197SStefano Zampini   total_counts = total_primal_vertices;
58279162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
58284641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
58299162d606SStefano Zampini       PetscInt *cols;
58309162d606SStefano Zampini 
58319162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
58329162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
58339162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
58349162d606SStefano Zampini         PetscInt    row = total_counts+k;
58359162d606SStefano Zampini         PetscScalar *vals;
58369162d606SStefano Zampini 
58379162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
58389162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
58399162d606SStefano Zampini       }
58409162d606SStefano Zampini       total_counts += constraints_n[i];
5841674ae819SStefano Zampini     }
5842674ae819SStefano Zampini   }
5843674ae819SStefano Zampini   /* assembling */
5844674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5845674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5846088faed8SStefano Zampini 
5847984c4197SStefano Zampini   /*
58486a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5849984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5850f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5851984c4197SStefano Zampini   */
5852674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5853674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5854026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5855984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5856984c4197SStefano Zampini     /* working stuff for GEQRF */
585781d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5858984c4197SStefano Zampini     PetscBLASInt lqr_work;
5859984c4197SStefano Zampini     /* working stuff for UNGQR */
5860984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5861984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5862984c4197SStefano Zampini     /* working stuff for TRTRS */
5863984c4197SStefano Zampini     PetscScalar  *trs_rhs;
58643f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5865984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5866984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5867984c4197SStefano Zampini     PetscScalar  *start_vals;
5868984c4197SStefano Zampini     /* working stuff for values insertion */
58694641a718SStefano Zampini     PetscBT      is_primal;
587064efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5871906d46d4SStefano Zampini     /* matrix sizes */
5872906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5873906d46d4SStefano Zampini     /* temporary change of basis */
5874906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5875cf5a6209SStefano Zampini     /* extra space for debugging */
5876cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5877984c4197SStefano Zampini 
5878906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5879906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
588016f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5881bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5882906d46d4SStefano Zampini     /* nonzeros for local mat */
5883bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
58841dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5885bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
58861dd7afcfSStefano Zampini     } else {
58871dd7afcfSStefano Zampini       const PetscInt *ii;
58881dd7afcfSStefano Zampini       PetscInt       n;
58891dd7afcfSStefano Zampini       PetscBool      flg_row;
58901dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
58911dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
58921dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
58931dd7afcfSStefano Zampini     }
58949162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5895a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
58969162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5897a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
58989162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5899a717540cSStefano Zampini         } else {
59009162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
59019162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5902a717540cSStefano Zampini         }
5903a717540cSStefano Zampini       }
5904a717540cSStefano Zampini     }
5905906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5906bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
59071dd7afcfSStefano Zampini     /* Set interior change in the matrix */
59081dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5909bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5910906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5911a717540cSStefano Zampini       }
59121dd7afcfSStefano Zampini     } else {
59131dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
59141dd7afcfSStefano Zampini       PetscScalar    *aa;
59151dd7afcfSStefano Zampini       PetscInt       n;
59161dd7afcfSStefano Zampini       PetscBool      flg_row;
59171dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
59181dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
59191dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
59201dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
59211dd7afcfSStefano Zampini       }
59221dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
59231dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
59241dd7afcfSStefano Zampini     }
5925a717540cSStefano Zampini 
5926a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5927a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5928a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5929a717540cSStefano Zampini     }
5930a717540cSStefano Zampini 
5931a717540cSStefano Zampini 
5932a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5933a717540cSStefano Zampini     /*
5934a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5935a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5936a717540cSStefano Zampini 
5937a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5938a717540cSStefano Zampini 
5939a6b551f4SStefano Zampini           - Using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified)
5940a6b551f4SStefano Zampini 
5941a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5942a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5943a717540cSStefano Zampini             |              ...                        |
5944a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5945a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5946a717540cSStefano Zampini 
5947a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5948a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5949a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5950a6b551f4SStefano Zampini 
5951a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5952a717540cSStefano Zampini     */
5953a717540cSStefano Zampini     if (qr_needed) {
5954984c4197SStefano Zampini       /* space to store Q */
5955854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
59564e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
59574e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5958984c4197SStefano Zampini       /* first we issue queries for optimal work */
59593f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
59603f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
59613f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5962984c4197SStefano Zampini       lqr_work = -1;
59633f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5964984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5965984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5966785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5967984c4197SStefano Zampini       lgqr_work = -1;
59683f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
59693f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
59703f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
59713f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
59723f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
59733f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5974984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5975984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5976785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5977984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5978785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5979a717540cSStefano Zampini       /* allocating workspace for check */
5980a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5981cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5982a717540cSStefano Zampini       }
5983a717540cSStefano Zampini     }
5984984c4197SStefano Zampini     /* array to store whether a node is primal or not */
59854641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5986473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
59870e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
5988eee23b56SStefano Zampini     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
598939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
599039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
599139e2fb2aSStefano Zampini     }
599239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5993984c4197SStefano Zampini 
5994a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
59959162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
59969162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
59974641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5998984c4197SStefano Zampini         /* get constraint info */
59999162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6000984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6001984c4197SStefano Zampini 
6002984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
60039162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %d: %d need a change of basis (size %d)\n",total_counts,primal_dofs,size_of_constraint);CHKERRQ(ierr);
6004674ae819SStefano Zampini         }
6005984c4197SStefano Zampini 
6006fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6007a717540cSStefano Zampini 
6008a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6009a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
60109162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6011a717540cSStefano Zampini           }
6012984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
60139162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6014984c4197SStefano Zampini 
6015984c4197SStefano Zampini           /* compute QR decomposition of constraints */
60163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
60173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
60183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6019674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60203f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6021984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6022674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6023984c4197SStefano Zampini 
6024984c4197SStefano Zampini           /* explictly compute R^-T */
6025984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6026984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
60273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
60283f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
60293f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
60303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6031984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60323f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6033984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6034984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6035984c4197SStefano Zampini 
6036a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
60373f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
60383f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
60393f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
60403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6041984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60423f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6043984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
6044984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6045984c4197SStefano Zampini 
6046984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6047984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6048984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
60493f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
60503f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
60513f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
60523f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
60533f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
60543f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6055984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60569162d606SStefano Zampini           PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&zero,constraints_data+constraints_data_ptr[total_counts],&Blas_LDC));
6057984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
60589162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6059984c4197SStefano Zampini 
6060984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
60619162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6062984c4197SStefano Zampini           /* insert cols for primal dofs */
6063984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6064984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
60659162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6066906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6067984c4197SStefano Zampini           }
6068984c4197SStefano Zampini           /* insert cols for dual dofs */
6069984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
60709162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6071984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
60729162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6073906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6074984c4197SStefano Zampini               j++;
6075674ae819SStefano Zampini             }
6076674ae819SStefano Zampini           }
6077984c4197SStefano Zampini 
6078984c4197SStefano Zampini           /* check change of basis */
6079984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6080984c4197SStefano Zampini             PetscInt   ii,jj;
6081984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6082c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6083c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6084c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6085c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6086c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6087c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6088984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6089cf5a6209SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&Blas_M,&Blas_N,&Blas_K,&one,dbg_work,&Blas_LDA,qr_basis,&Blas_LDB,&zero,&dbg_work[size_of_constraint*primal_dofs],&Blas_LDC));
6090984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6091984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6092984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6093cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6094cf5a6209SStefano Zampini                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
6095674ae819SStefano Zampini               }
6096674ae819SStefano Zampini             }
6097984c4197SStefano Zampini             if (!valid_qr) {
609822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6099984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6100984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6101cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6102cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6103674ae819SStefano Zampini                   }
6104cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
6105cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6106984c4197SStefano Zampini                   }
6107984c4197SStefano Zampini                 }
6108984c4197SStefano Zampini               }
6109674ae819SStefano Zampini             } else {
611022d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6111674ae819SStefano Zampini             }
6112674ae819SStefano Zampini           }
6113a717540cSStefano Zampini         } else { /* simple transformation block */
6114a717540cSStefano Zampini           PetscInt    row,col;
6115a6b551f4SStefano Zampini           PetscScalar val,norm;
6116a6b551f4SStefano Zampini 
6117a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
61189162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,constraints_data+constraints_data_ptr[total_counts],&Blas_one,constraints_data+constraints_data_ptr[total_counts],&Blas_one));
6119a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
61209162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
61219162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6122bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
61239162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6124906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
61259162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6126a717540cSStefano Zampini             } else {
6127a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
61289162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6129a717540cSStefano Zampini                 if (row != col) {
61309162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6131a717540cSStefano Zampini                 } else {
61329162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6133a717540cSStefano Zampini                 }
6134906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6135a717540cSStefano Zampini               }
6136a717540cSStefano Zampini             }
6137a717540cSStefano Zampini           }
613898a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
613922d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6140a717540cSStefano Zampini           }
6141674ae819SStefano Zampini         }
6142984c4197SStefano Zampini       } else {
6143984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
61449162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,size_of_constraint);CHKERRQ(ierr);
6145674ae819SStefano Zampini         }
6146674ae819SStefano Zampini       }
6147674ae819SStefano Zampini     }
6148a717540cSStefano Zampini 
6149a717540cSStefano Zampini     /* free workspace */
6150a717540cSStefano Zampini     if (qr_needed) {
6151984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6152cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6153984c4197SStefano Zampini       }
6154984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6155984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6156984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6157984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6158984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6159674ae819SStefano Zampini     }
6160a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6161906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6162906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6163906d46d4SStefano Zampini 
6164906d46d4SStefano Zampini     /* assembling of global change of variable */
616588c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6166bbb9e6c6SStefano Zampini       Mat      tmat;
616716f15bc4SStefano Zampini       PetscInt bs;
616816f15bc4SStefano Zampini 
6169906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6170906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6171bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6172bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6173bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6174bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
617516f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
617616f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6177906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6178bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6179bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6180bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6181bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6182bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6183e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6184e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6185bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6186bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
618788c03ad3SStefano Zampini 
6188906d46d4SStefano Zampini       /* check */
6189906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6190906d46d4SStefano Zampini         PetscReal error;
6191906d46d4SStefano Zampini         Vec       x,x_change;
6192906d46d4SStefano Zampini 
6193906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6194906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6195906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6196906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6197e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6198e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6199bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6200e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6201e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6202906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6203906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6204906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6205637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6206637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6207637e8532SStefano Zampini         }
6208906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6209906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6210906d46d4SStefano Zampini       }
6211b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6212b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6213b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6214bf3a8328SStefano Zampini 
62159a962809SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
6216b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6217ac632422SStefano Zampini           Mat                    S_new,tmat;
6218bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6219bbb9e6c6SStefano Zampini 
6220bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
62217dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6222bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6223bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6224bf3a8328SStefano Zampini             IS                     is_V;
6225b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6226b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6227b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6228b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6229b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6230bf3a8328SStefano Zampini           }
6231bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6232ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6233b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6234ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6235bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6236bf3a8328SStefano Zampini             const PetscScalar *array;
6237bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6238bf3a8328SStefano Zampini             PetscInt          i,n_V;
6239bf3a8328SStefano Zampini 
6240b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6241b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6242b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6243b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6244b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6245b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6246b087196eSStefano Zampini               PetscScalar val;
6247b087196eSStefano Zampini               PetscInt    idx;
6248b087196eSStefano Zampini 
6249b087196eSStefano Zampini               idx = idxs_V[i];
6250b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6251b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6252b087196eSStefano Zampini             }
6253b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6254b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6255bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6256bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6257bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6258bf3a8328SStefano Zampini           }
6259ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6260ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6261ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6262ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6263b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6264ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6265bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6266b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6267bf3a8328SStefano Zampini             }
6268ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6269ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6270ac632422SStefano Zampini           }
6271b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
627288c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6273b96c3477SStefano Zampini         }
6274c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6275b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6276c9db6a07SStefano Zampini           PetscInt i;
6277c9db6a07SStefano Zampini 
6278c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6279c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6280c9db6a07SStefano Zampini           }
6281c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6282c9db6a07SStefano Zampini         }
6283b96c3477SStefano Zampini       }
628416909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
628516909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
628616909a7fSStefano Zampini       } else {
6287906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
628816909a7fSStefano Zampini       }
62891dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
629027b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
629172b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
629272b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
629372b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
629472b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
629572b8c272SStefano Zampini     }
62961dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
629727b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6298b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6299b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6300906d46d4SStefano Zampini     } else {
63011dd7afcfSStefano Zampini       Mat benign_global = NULL;
630227b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
63031dd7afcfSStefano Zampini         Mat tmat;
63041dd7afcfSStefano Zampini 
63051dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
63061dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
63071dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
63081dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
63091dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
63101dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
63111dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
63121dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
63131dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
63141dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
63151dd7afcfSStefano Zampini           Mat M;
63161dd7afcfSStefano Zampini 
63171dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
63181dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
63191dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
63201dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6321906d46d4SStefano Zampini         } else {
63221dd7afcfSStefano Zampini           Mat         eye;
63231dd7afcfSStefano Zampini           PetscScalar *array;
63241dd7afcfSStefano Zampini 
63251dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
63261dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
63271dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
63281dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6329906d46d4SStefano Zampini           }
63301dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
63311dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63321dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63331dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
63341dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
63351dd7afcfSStefano Zampini         }
63361dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
63371dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
63381dd7afcfSStefano Zampini       }
63391dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
63401dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
63411dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
634227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
63431dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
63441dd7afcfSStefano Zampini       }
63451dd7afcfSStefano Zampini     }
634616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
634716909a7fSStefano Zampini       IS             is_global;
634816909a7fSStefano Zampini       const PetscInt *gidxs;
634916909a7fSStefano Zampini 
635016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
635116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
635216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
63537dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
635416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
635516909a7fSStefano Zampini     }
63561dd7afcfSStefano Zampini   }
63571dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
63581dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6359b9b85e73SStefano Zampini   }
6360a717540cSStefano Zampini 
636172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
63624f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
63634f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
63644f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
63654f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6366019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6367019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6368019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6369019a44ceSStefano Zampini     }
6370019a44ceSStefano Zampini 
6371019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6372727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6373727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
63749f47a83aSStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6375c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
63760e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
63779f47a83aSStefano Zampini         ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6378727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6379727cdba6SStefano Zampini       }
63800e6343abSStefano Zampini     }
6381727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6382b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
638372b8c272SStefano Zampini   }
638472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6385727cdba6SStefano Zampini 
6386a717540cSStefano Zampini   /* flush dbg viewer */
6387b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6388b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6389b8ffe317SStefano Zampini   }
6390a717540cSStefano Zampini 
6391e310c8b4SStefano Zampini   /* free workspace */
6392a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
63934641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
639408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
63959162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
63969162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
639708122e43SStefano Zampini   } else {
63989162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
63999162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
64009162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
640108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
640208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
64039162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
64049162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
640508122e43SStefano Zampini   }
6406674ae819SStefano Zampini   PetscFunctionReturn(0);
6407674ae819SStefano Zampini }
6408674ae819SStefano Zampini 
6409674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6410674ae819SStefano Zampini {
641171582508SStefano Zampini   ISLocalToGlobalMapping map;
6412674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6413674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
641466da6bd7Sstefano_zampini   PetscInt               i,N;
641566da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
641666da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6417674ae819SStefano Zampini 
6418674ae819SStefano Zampini   PetscFunctionBegin;
64198af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6420b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
64218e61c736SStefano Zampini     /* Reset previously computed graph */
64228e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6423674ae819SStefano Zampini     /* Init local Graph struct */
64247fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
642571582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6426be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6427674ae819SStefano Zampini 
64287a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
64297a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
64307a0e7b2cSstefano_zampini     }
6431575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
64329a962809SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %d, expected %d\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
64339577ea80SStefano Zampini 
6434674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
643566da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
64364d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
64374d379d7bSStefano Zampini       PetscInt  nvtxs;
6438e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6439674ae819SStefano Zampini 
64402fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
64412fffb893SStefano Zampini       if (flg_row) {
64424d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6443b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
64442fffb893SStefano Zampini       }
64452fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
644666da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6447674ae819SStefano Zampini     }
64489b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
64499b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6450674ae819SStefano Zampini     }
6451674ae819SStefano Zampini 
6452674ae819SStefano Zampini     /* Setup of Graph */
64534b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
645414f95afaSStefano Zampini     ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
6455674ae819SStefano Zampini 
64564f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
64574f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
64584f1b2e48SStefano Zampini       PetscInt *local_subs;
64594f1b2e48SStefano Zampini 
64604f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
64614f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
64624f1b2e48SStefano Zampini         const PetscInt *idxs;
64634f1b2e48SStefano Zampini         PetscInt       nl,j;
64644f1b2e48SStefano Zampini 
64654f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
64664f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
646771582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
64684f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
64694f1b2e48SStefano Zampini       }
64704f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
64714f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
64724f1b2e48SStefano Zampini     }
64738af8fcf9SStefano Zampini   }
64744f1b2e48SStefano Zampini 
6475cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6476674ae819SStefano Zampini     /* Graph's connected components analysis */
6477674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
647871582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
64798af8fcf9SStefano Zampini   }
648066da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6481674ae819SStefano Zampini   PetscFunctionReturn(0);
6482674ae819SStefano Zampini }
6483674ae819SStefano Zampini 
64849a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
64859a7d3425SStefano Zampini {
64869a7d3425SStefano Zampini   PetscInt       i,j;
64879a7d3425SStefano Zampini   PetscScalar    *alphas;
64889a7d3425SStefano Zampini   PetscErrorCode ierr;
64899a7d3425SStefano Zampini 
64909a7d3425SStefano Zampini   PetscFunctionBegin;
6491785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
64929a7d3425SStefano Zampini   for (i=0;i<n;i++) {
64939a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6494669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6495669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6496669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
64979a7d3425SStefano Zampini   }
64989a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
64999a7d3425SStefano Zampini   PetscFunctionReturn(0);
65009a7d3425SStefano Zampini }
65019a7d3425SStefano Zampini 
6502bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6503e7931f94SStefano Zampini {
650457de7509SStefano Zampini   Mat            A;
6505e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6506e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
650752e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
650852e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6509bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
651057de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
651127b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
651227b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
651327b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
651427b6a85dSStefano Zampini   MPI_Comm       subcomm;
651552e5ac9dSStefano Zampini   PetscErrorCode ierr;
6516a57a6d2fSStefano Zampini 
6517e7931f94SStefano Zampini   PetscFunctionBegin;
651857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
651957de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6520fbfcfee5SBarry Smith   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",PETSC_FUNCTION_NAME);
652157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
652257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
652357de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
652457de7509SStefano Zampini 
652557de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
652657de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
652757de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
652857de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
652957de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6530bb360cb4SStefano Zampini   im_active = !!n;
653157de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
653257de7509SStefano Zampini   void_procs = size - active_procs;
653357de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
653457de7509SStefano Zampini   if (void_procs) {
653557de7509SStefano Zampini     PetscInt ncand;
653657de7509SStefano Zampini 
653757de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
653857de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
653957de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
654057de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
654157de7509SStefano Zampini       if (!procs_candidates[i]) {
654257de7509SStefano Zampini         procs_candidates[ncand++] = i;
654357de7509SStefano Zampini       }
654457de7509SStefano Zampini     }
654557de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
654657de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
654757de7509SStefano Zampini   }
654857de7509SStefano Zampini 
6549bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
655014f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
6551bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
6552bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
655314f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
655414f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
655514f0bfb9SStefano Zampini     else dest = rank;
655657de7509SStefano Zampini     if (im_active) {
655757de7509SStefano Zampini       issize = 1;
655857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
655914f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
656057de7509SStefano Zampini       } else {
656114f0bfb9SStefano Zampini         isidx = dest;
656257de7509SStefano Zampini       }
656357de7509SStefano Zampini     } else {
656457de7509SStefano Zampini       issize = 0;
656557de7509SStefano Zampini       isidx = -1;
656657de7509SStefano Zampini     }
6567bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
656857de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6569daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
657057de7509SStefano Zampini     PetscFunctionReturn(0);
657157de7509SStefano Zampini   }
6572c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6573c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
657427b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6575e7931f94SStefano Zampini 
6576e7931f94SStefano Zampini   /* Get info on mapping */
65773bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6578e7931f94SStefano Zampini 
6579e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6580785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6581e7931f94SStefano Zampini   xadj[0] = 0;
6582e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6583785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6584785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
6585bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
658627b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
658727b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
658827b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6589e7931f94SStefano Zampini 
659027b6a85dSStefano Zampini   xadj_count = 0;
65912b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
659227b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
659327b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6594d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6595d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6596d023bfaeSStefano Zampini         xadj_count++;
659727b6a85dSStefano Zampini         break;
659827b6a85dSStefano Zampini       }
6599e7931f94SStefano Zampini     }
6600e7931f94SStefano Zampini   }
6601d023bfaeSStefano Zampini   xadj[1] = xadj_count;
660227b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
66033bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6604e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6605e7931f94SStefano Zampini 
66063837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6607e7931f94SStefano Zampini 
660827b6a85dSStefano Zampini   /* Restrict work on active processes only */
660927b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
661027b6a85dSStefano Zampini   if (void_procs) {
661127b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
661227b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
661327b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
661427b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
661527b6a85dSStefano Zampini   } else {
661627b6a85dSStefano Zampini     psubcomm = NULL;
661727b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
661827b6a85dSStefano Zampini   }
661927b6a85dSStefano Zampini 
662027b6a85dSStefano Zampini   v_wgt = NULL;
662127b6a85dSStefano Zampini   if (!color) {
6622e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6623e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6624e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6625c8587f34SStefano Zampini   } else {
662652e5ac9dSStefano Zampini     Mat             subdomain_adj;
662752e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
662852e5ac9dSStefano Zampini     MatPartitioning partitioner;
662927b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
663052e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
663157de7509SStefano Zampini     PetscMPIInt     size;
6632b0c7d250SStefano Zampini     PetscBool       aggregate;
6633b0c7d250SStefano Zampini 
663427b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
663527b6a85dSStefano Zampini     if (void_procs) {
663627b6a85dSStefano Zampini       PetscInt prank = rank;
6637785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
663827b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6639e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6640e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6641c8587f34SStefano Zampini       }
6642e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
664327b6a85dSStefano Zampini     } else {
664427b6a85dSStefano Zampini       oldranks = NULL;
664527b6a85dSStefano Zampini     }
6646b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
664727b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6648b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6649b0c7d250SStefano Zampini       PetscMPIInt nrank;
6650b0c7d250SStefano Zampini       PetscScalar *vals;
6651b0c7d250SStefano Zampini 
665227b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6653b0c7d250SStefano Zampini       lrows = 0;
6654b0c7d250SStefano Zampini       if (nrank<redprocs) {
6655b0c7d250SStefano Zampini         lrows = size/redprocs;
6656b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6657b0c7d250SStefano Zampini       }
665827b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6659b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6660b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6661b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6662b0c7d250SStefano Zampini       row = nrank;
6663b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6664b0c7d250SStefano Zampini       cols = adjncy;
6665b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6666b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6667b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6668b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6669b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
667052e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
667152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
667252e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6673b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
667427b6a85dSStefano Zampini       if (use_vwgt) {
667527b6a85dSStefano Zampini         Vec               v;
667627b6a85dSStefano Zampini         const PetscScalar *array;
667727b6a85dSStefano Zampini         PetscInt          nl;
667827b6a85dSStefano Zampini 
667927b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
6680bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
668127b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
668227b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
668327b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
668427b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
668527b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
668622db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
668727b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
668827b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
668927b6a85dSStefano Zampini       }
6690b0c7d250SStefano Zampini     } else {
669127b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
669227b6a85dSStefano Zampini       if (use_vwgt) {
669327b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
6694bb360cb4SStefano Zampini         v_wgt[0] = n;
669527b6a85dSStefano Zampini       }
6696b0c7d250SStefano Zampini     }
669722b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6698e7931f94SStefano Zampini 
6699e7931f94SStefano Zampini     /* Partition */
670027b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6701e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
670227b6a85dSStefano Zampini     if (v_wgt) {
6703e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6704c8587f34SStefano Zampini     }
670557de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
670657de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6707e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6708e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
670922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6710e7931f94SStefano Zampini 
671152e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
67126583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
671352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
671452e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
671557de7509SStefano Zampini     if (!aggregate) {
671657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
671727b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
671827b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
671927b6a85dSStefano Zampini #endif
672057de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
672127b6a85dSStefano Zampini       } else if (oldranks) {
6722b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
672327b6a85dSStefano Zampini       } else {
672427b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
672557de7509SStefano Zampini       }
672628143c3dSStefano Zampini     } else {
6727b0c7d250SStefano Zampini       PetscInt    idxs[1];
6728b0c7d250SStefano Zampini       PetscMPIInt tag;
6729b0c7d250SStefano Zampini       MPI_Request *reqs;
6730b0c7d250SStefano Zampini 
6731b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6732b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6733b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
673427b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
673528143c3dSStefano Zampini       }
673627b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6737b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6738b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
673957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
674027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
674127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
674227b6a85dSStefano Zampini #endif
674357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
674427b6a85dSStefano Zampini       } else if (oldranks) {
6745b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
674627b6a85dSStefano Zampini       } else {
674727b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6748e7931f94SStefano Zampini       }
674957de7509SStefano Zampini     }
675052e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6751e7931f94SStefano Zampini     /* clean up */
6752e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
675352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6754e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6755e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6756e7931f94SStefano Zampini   }
675727b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
675857de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6759e7931f94SStefano Zampini 
6760e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6761e7931f94SStefano Zampini   i = 1;
676227b6a85dSStefano Zampini   if (!color) i=0;
676357de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6764e7931f94SStefano Zampini   PetscFunctionReturn(0);
6765e7931f94SStefano Zampini }
6766e7931f94SStefano Zampini 
6767e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6768e7931f94SStefano Zampini 
67691e0482f5SStefano Zampini PetscErrorCode PCBDDCMatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, PetscBool reuse, Mat *mat_n, PetscInt nis, IS isarray[], PetscInt nvecs, Vec nnsp_vec[])
6770e7931f94SStefano Zampini {
677170cf5478SStefano Zampini   Mat                    local_mat;
6772e7931f94SStefano Zampini   IS                     is_sends_internal;
67739d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
67741ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
67759d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6776e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6777e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6778e7931f94SStefano Zampini   const PetscInt*        is_indices;
6779e7931f94SStefano Zampini   MatType                new_local_type;
6780e7931f94SStefano Zampini   /* buffers */
6781e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
678228143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
67839d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6784e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
67851ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6786e7931f94SStefano Zampini   /* MPI */
678728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
678828143c3dSStefano Zampini   PetscSubcomm           subcomm;
6789e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
679028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
679128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
67921ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
67931ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
67941ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6795e7931f94SStefano Zampini   PetscErrorCode         ierr;
6796e7931f94SStefano Zampini 
6797e7931f94SStefano Zampini   PetscFunctionBegin;
679857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6799e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6800fbfcfee5SBarry Smith   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",PETSC_FUNCTION_NAME);
680157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
680257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
680357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
680457de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
680557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
68061ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
68071ae86dd6SStefano Zampini   if (nvecs) {
68081ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
68091ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
68101ae86dd6SStefano Zampini   }
681157de7509SStefano Zampini   /* further checks */
6812e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6813e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6814e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6815e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6816e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
681757de7509SStefano Zampini   if (reuse && *mat_n) {
681870cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
681957de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
682070cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
682128143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
682270cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
682370cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
682470cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
682570cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
682670cf5478SStefano Zampini   }
6827e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6828e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
682957de7509SStefano Zampini 
6830e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6831e7931f94SStefano Zampini   if (!is_sends) {
683228143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
6833bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6834c8587f34SStefano Zampini   } else {
6835e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6836e7931f94SStefano Zampini     is_sends_internal = is_sends;
6837c8587f34SStefano Zampini   }
6838e7931f94SStefano Zampini 
6839e7931f94SStefano Zampini   /* get comm */
6840a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6841e7931f94SStefano Zampini 
6842e7931f94SStefano Zampini   /* compute number of sends */
6843e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6844e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6845e7931f94SStefano Zampini 
6846e7931f94SStefano Zampini   /* compute number of receives */
6847e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6848785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6849e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6850e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6851e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6852e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6853e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6854e7931f94SStefano Zampini 
685528143c3dSStefano Zampini   /* restrict comm if requested */
685628143c3dSStefano Zampini   subcomm = 0;
685728143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
685828143c3dSStefano Zampini   if (restrict_comm) {
6859779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6860779c1cceSStefano Zampini 
686128143c3dSStefano Zampini     color = 0;
686253a05cb3SStefano Zampini     if (restrict_full) {
686353a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
686453a05cb3SStefano Zampini     } else {
686553a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
686653a05cb3SStefano Zampini     }
6867b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
686828143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
686928143c3dSStefano Zampini     /* check if reuse has been requested */
687057de7509SStefano Zampini     if (reuse) {
687128143c3dSStefano Zampini       if (*mat_n) {
687228143c3dSStefano Zampini         PetscMPIInt subcommsize2;
687328143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
687428143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
687528143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
687628143c3dSStefano Zampini       } else {
687728143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
687828143c3dSStefano Zampini       }
687928143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6880779c1cceSStefano Zampini       PetscMPIInt rank;
6881779c1cceSStefano Zampini 
6882779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
688328143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
688428143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
688528143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6886306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
688728143c3dSStefano Zampini     }
688828143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
688928143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
689028143c3dSStefano Zampini   } else {
689128143c3dSStefano Zampini     comm_n = comm;
689228143c3dSStefano Zampini   }
689328143c3dSStefano Zampini 
6894e7931f94SStefano Zampini   /* prepare send/receive buffers */
6895785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6896e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6897785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6898e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
689928143c3dSStefano Zampini   if (nis) {
6900854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
690128143c3dSStefano Zampini   }
6902e7931f94SStefano Zampini 
690328143c3dSStefano Zampini   /* Get data from local matrices */
69046c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6905e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6906e7931f94SStefano Zampini     /*
6907e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6908e7931f94SStefano Zampini        send_buffer_idxs should contain:
6909e7931f94SStefano Zampini        - MatType_PRIVATE type
6910e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6911e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6912e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6913e7931f94SStefano Zampini     */
69146c4ed002SBarry Smith   else {
6915e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
69163bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6917854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6918e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6919e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
69203bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6921e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
69223bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6923e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6924e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6925e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6926e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6927c8587f34SStefano Zampini     }
6928c8587f34SStefano Zampini   }
6929e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
693028143c3dSStefano Zampini   /* additional is (if any) */
693128143c3dSStefano Zampini   if (nis) {
693228143c3dSStefano Zampini     PetscMPIInt psum;
693328143c3dSStefano Zampini     PetscInt j;
693428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
693528143c3dSStefano Zampini       PetscInt plen;
693628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
693728143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
693828143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
693928143c3dSStefano Zampini     }
6940854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
694128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
694228143c3dSStefano Zampini       PetscInt plen;
694328143c3dSStefano Zampini       const PetscInt *is_array_idxs;
694428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
694528143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
694628143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
694728143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
694828143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
694928143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
695028143c3dSStefano Zampini     }
695128143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
695228143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
695328143c3dSStefano Zampini     }
695428143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
695528143c3dSStefano Zampini   }
69563b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
695728143c3dSStefano Zampini 
6958e7931f94SStefano Zampini   buf_size_idxs = 0;
6959e7931f94SStefano Zampini   buf_size_vals = 0;
696028143c3dSStefano Zampini   buf_size_idxs_is = 0;
69611ae86dd6SStefano Zampini   buf_size_vecs = 0;
6962e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6963e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6964e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
696528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
69661ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6967e7931f94SStefano Zampini   }
6968785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6969785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
697095ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
69711ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6972e7931f94SStefano Zampini 
6973e7931f94SStefano Zampini   /* get new tags for clean communications */
6974e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6975e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
697628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
69771ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6978e7931f94SStefano Zampini 
6979e7931f94SStefano Zampini   /* allocate for requests */
6980785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6981785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
698295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
69831ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6984785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6985785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
698695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
69871ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6988e7931f94SStefano Zampini 
6989e7931f94SStefano Zampini   /* communications */
6990e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6991e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
699228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
69931ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6994e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6995e7931f94SStefano Zampini     source_dest = onodes[i];
6996e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6997e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6998e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6999e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
700028143c3dSStefano Zampini     if (nis) {
700157de7509SStefano Zampini       source_dest = onodes_is[i];
700228143c3dSStefano Zampini       ierr = MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]);CHKERRQ(ierr);
700328143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
700428143c3dSStefano Zampini     }
70051ae86dd6SStefano Zampini     if (nvecs) {
70061ae86dd6SStefano Zampini       source_dest = onodes[i];
70071ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
70081ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
70091ae86dd6SStefano Zampini     }
7010e7931f94SStefano Zampini   }
7011e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7012e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7013e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7014e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
701528143c3dSStefano Zampini     if (nis) {
701628143c3dSStefano Zampini       ierr = MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i]);CHKERRQ(ierr);
701728143c3dSStefano Zampini     }
70181ae86dd6SStefano Zampini     if (nvecs) {
70191ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
70201ae86dd6SStefano Zampini       ierr = MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]);CHKERRQ(ierr);
70211ae86dd6SStefano Zampini     }
7022e7931f94SStefano Zampini   }
7023e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7024e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7025e7931f94SStefano Zampini 
7026e7931f94SStefano Zampini   /* assemble new l2g map */
7027e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7028e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
70299d30be91SStefano Zampini   new_local_rows = 0;
7030e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
70319d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7032e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7033e7931f94SStefano Zampini   }
70349d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7035e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
70369d30be91SStefano Zampini   new_local_rows = 0;
7037e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
70389d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
70399d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7040e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7041e7931f94SStefano Zampini   }
70429d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
70439d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7044e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7045e7931f94SStefano Zampini 
7046e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7047e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7048e7931f94SStefano Zampini   /* it also assumes that if the block size is set, than it is the same among all local matrices (see checks at the beginning of the function) */
7049e7931f94SStefano Zampini   if (n_recvs) {
705028143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7051e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7052e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7053e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7054e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7055e7931f94SStefano Zampini         break;
7056e7931f94SStefano Zampini       }
7057e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7058e7931f94SStefano Zampini     }
7059e7931f94SStefano Zampini     switch (new_local_type_private) {
706028143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7061e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7062e7931f94SStefano Zampini         bs = 1;
7063e7931f94SStefano Zampini         break;
7064e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7065e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7066e7931f94SStefano Zampini         bs = 1;
7067e7931f94SStefano Zampini         break;
7068e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7069e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7070e7931f94SStefano Zampini         break;
7071e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7072e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7073e7931f94SStefano Zampini         break;
7074e7931f94SStefano Zampini       default:
7075fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7076e7931f94SStefano Zampini         break;
7077e7931f94SStefano Zampini     }
7078ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7079ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
708028143c3dSStefano Zampini     bs = 1;
7081e7931f94SStefano Zampini   }
7082e7931f94SStefano Zampini 
708370cf5478SStefano Zampini   /* create MATIS object if needed */
708457de7509SStefano Zampini   if (!reuse) {
7085e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7086e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
708770cf5478SStefano Zampini   } else {
708870cf5478SStefano Zampini     /* it also destroys the local matrices */
708957de7509SStefano Zampini     if (*mat_n) {
709070cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
709157de7509SStefano Zampini     } else { /* this is a fake object */
709257de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
709357de7509SStefano Zampini     }
709470cf5478SStefano Zampini   }
709570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7096e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
70979d30be91SStefano Zampini 
70989d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
70999d30be91SStefano Zampini 
71009d30be91SStefano Zampini   /* Global to local map of received indices */
71019d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
71029d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
71039d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
71049d30be91SStefano Zampini 
71059d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
71069d30be91SStefano Zampini   buf_size_idxs = 0;
71079d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
71089d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
71099d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
71109d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
71119d30be91SStefano Zampini   }
71129d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
71139d30be91SStefano Zampini 
71149d30be91SStefano Zampini   /* set preallocation */
71159d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
71169d30be91SStefano Zampini   if (!newisdense) {
71179d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
71189d30be91SStefano Zampini 
71199d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
71209d30be91SStefano Zampini     if (n_recvs) {
71219d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
71229d30be91SStefano Zampini     }
71239d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
71249d30be91SStefano Zampini       PetscInt j;
71259d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
71269d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
71279d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
71289d30be91SStefano Zampini         }
71299d30be91SStefano Zampini       } else {
71309d30be91SStefano Zampini         /* TODO */
71319d30be91SStefano Zampini       }
71329d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
71339d30be91SStefano Zampini     }
71349d30be91SStefano Zampini     if (new_local_nnz) {
71359d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
71369d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
71379d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
71389d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
71399d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
71409d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
71419d30be91SStefano Zampini     } else {
71429d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
71439d30be91SStefano Zampini     }
71449d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
71459d30be91SStefano Zampini   } else {
71469d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
71479d30be91SStefano Zampini   }
7148e7931f94SStefano Zampini 
7149e7931f94SStefano Zampini   /* set values */
7150e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
71519d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7152e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7153e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7154e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
71559d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7156e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7157e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7158e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
715928143c3dSStefano Zampini     } else {
716028143c3dSStefano Zampini       /* TODO */
7161e7931f94SStefano Zampini     }
7162e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7163e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7164e7931f94SStefano Zampini   }
7165e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7166e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
71673b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
716870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
716970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
71709d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7171e7931f94SStefano Zampini 
7172dfd14d43SStefano Zampini #if 0
717328143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7174e7931f94SStefano Zampini     Vec       lvec,rvec;
7175e7931f94SStefano Zampini     PetscReal infty_error;
7176e7931f94SStefano Zampini 
71772a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7178e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7179e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7180e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
718170cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7182e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7183e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7184e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7185e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7186e7931f94SStefano Zampini   }
718728143c3dSStefano Zampini #endif
7188e7931f94SStefano Zampini 
718928143c3dSStefano Zampini   /* assemble new additional is (if any) */
719028143c3dSStefano Zampini   if (nis) {
719128143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
719228143c3dSStefano Zampini 
719328143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7194854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
719528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
719628143c3dSStefano Zampini     psum = 0;
719728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
719828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
719928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
720028143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
720128143c3dSStefano Zampini         psum += plen;
720228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
720328143c3dSStefano Zampini       }
720428143c3dSStefano Zampini     }
7205854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7206854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
720728143c3dSStefano Zampini     for (i=1;i<nis;i++) {
720828143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
720928143c3dSStefano Zampini     }
721028143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
721128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
721228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
721328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
721428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
721528143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
721628143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
721728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
721828143c3dSStefano Zampini       }
721928143c3dSStefano Zampini     }
722028143c3dSStefano Zampini     for (i=0;i<nis;i++) {
722128143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
722228143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
722328143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
722428143c3dSStefano Zampini     }
722528143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
722628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
722728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
722828143c3dSStefano Zampini   }
7229e7931f94SStefano Zampini   /* free workspace */
723028143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7231e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7232e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7233e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7234e7931f94SStefano Zampini   if (isdense) {
7235e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7236e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
72373b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7238e7931f94SStefano Zampini   } else {
7239e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7240e7931f94SStefano Zampini   }
724128143c3dSStefano Zampini   if (nis) {
724228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
724328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
724428143c3dSStefano Zampini   }
72451ae86dd6SStefano Zampini 
72461ae86dd6SStefano Zampini   if (nvecs) {
72471ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
72481ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
72491ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
72501ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
72511ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
72521ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
72531ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
72541ae86dd6SStefano Zampini     /* set values */
72551ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
72561ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
72571ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
72581ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
72591ae86dd6SStefano Zampini       PetscInt j;
72601ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
72611ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
72621ae86dd6SStefano Zampini       }
72631ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
72641ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
72651ae86dd6SStefano Zampini     }
72661ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
72671ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
72681ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
72691ae86dd6SStefano Zampini   }
72701ae86dd6SStefano Zampini 
72711ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
72721ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7273e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7274e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
72751ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
727628143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7277e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7278e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
72791ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
728028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7281e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7282e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7283e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7284e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7285e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
728628143c3dSStefano Zampini   if (nis) {
728728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
728828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
728928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
729028143c3dSStefano Zampini   }
729128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
729228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
729328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
729428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
729528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
729628143c3dSStefano Zampini     }
72971ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
72981ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
72991ae86dd6SStefano Zampini     }
730053a05cb3SStefano Zampini     *mat_n = NULL;
730128143c3dSStefano Zampini   }
7302e7931f94SStefano Zampini   PetscFunctionReturn(0);
7303e7931f94SStefano Zampini }
7304a57a6d2fSStefano Zampini 
730512edc857SStefano Zampini /* temporary hack into ksp private data structure */
7306af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
730712edc857SStefano Zampini 
7308c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7309c8587f34SStefano Zampini {
7310c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7311c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
731220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
73131ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
73141e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
73159881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
731620a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
73176e683305SStefano Zampini   IS                     coarse_is,*isarray;
73186e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
731930368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7320f9eb5b7dSStefano Zampini   PC                     pc_temp;
7321c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7322c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7323f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
73244f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
73251e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
732668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
732722bc73bbSStefano Zampini   PetscScalar            *array;
732857de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
732957de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
73307de4f681Sstefano_zampini   PetscMPIInt            commsize;
73319881197aSStefano Zampini   PetscErrorCode         ierr;
7332fdc09c96SStefano Zampini 
7333c8587f34SStefano Zampini   PetscFunctionBegin;
7334c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
733568457ee5SStefano Zampini   if (pcbddc->new_primal_space || pcbddc->coarse_size == -1) { /* a new primal space is present or it is the first initialization, so recompute global numbering */
7336fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
73375a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
73387de4f681Sstefano_zampini 
73397de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7340fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7341f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7342f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7343f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7344fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
734551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
734651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7347727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7348fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7349fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7350fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7351f4ddd8eeSStefano Zampini       }
7352fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7353fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7354f4ddd8eeSStefano Zampini     }
735570cf5478SStefano Zampini     /* reset any subassembling information */
735657de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
735770cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
735857de7509SStefano Zampini     }
73596e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7360fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7361f4ddd8eeSStefano Zampini   }
736257de7509SStefano Zampini   /* assemble coarse matrix */
736357de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
736457de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
736557de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
736657de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
736718a45a71SStefano Zampini   } else {
736857de7509SStefano Zampini     coarse_mat = NULL;
736957de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
73706e683305SStefano Zampini   }
7371e7931f94SStefano Zampini 
7372abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7373abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7374abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7375abbbba34SStefano Zampini 
7376abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
737722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
737822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
737922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
738022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7381e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,NULL,&t_coarse_mat_is);CHKERRQ(ierr);
73826e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
73836e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
73846e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7385abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7386abbbba34SStefano Zampini 
738757de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
738857de7509SStefano Zampini   im_active = !!(pcis->n);
738957de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
739057de7509SStefano Zampini 
739114f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
739257de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
739357de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
73947de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
739557de7509SStefano Zampini   coarse_mat_is = NULL;
739657de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
739757de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
73981ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
739957de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
740057de7509SStefano Zampini   if (multilevel_requested) {
740157de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
740257de7509SStefano Zampini     restr = PETSC_FALSE;
740357de7509SStefano Zampini     full_restr = PETSC_FALSE;
740457de7509SStefano Zampini   } else {
740557de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
740657de7509SStefano Zampini     restr = PETSC_TRUE;
740757de7509SStefano Zampini     full_restr = PETSC_TRUE;
740857de7509SStefano Zampini   }
74097de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
741057de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
741157de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7412a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7413bb360cb4SStefano Zampini       if (multilevel_requested) {
7414bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7415bb360cb4SStefano Zampini       } else {
7416bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7417bb360cb4SStefano Zampini       }
7418a198735bSStefano Zampini     } else {
74197de4f681Sstefano_zampini       PetscMPIInt rank;
7420a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
74217de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7422a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7423a198735bSStefano Zampini     }
742457de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
742557de7509SStefano Zampini     PetscInt    psum;
742657de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
742757de7509SStefano Zampini     else psum = 0;
742857de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
74297de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
743057de7509SStefano Zampini   }
743157de7509SStefano Zampini   /* determine if we can go multilevel */
743257de7509SStefano Zampini   if (multilevel_requested) {
743357de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
743457de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
743557de7509SStefano Zampini   }
743657de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
743757de7509SStefano Zampini 
7438e4d548c7SStefano Zampini   /* dump subassembling pattern */
7439e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7440e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7441e4d548c7SStefano Zampini   }
7442e4d548c7SStefano Zampini 
74436e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
74441e0482f5SStefano Zampini   nedcfield = -1;
74451e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
74466e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
74476e683305SStefano Zampini     const PetscInt         *idxs;
74486e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
74496e683305SStefano Zampini 
74506e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
74510be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
74526e683305SStefano Zampini     /* allocate space for temporary storage */
7453854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7454854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
74556e683305SStefano Zampini     /* allocate for IS array */
74566e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
74571e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
74581e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
74591e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
74601e0482f5SStefano Zampini       } else {
74611e0482f5SStefano Zampini         nedcfield = 0;
74621e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
74631e0482f5SStefano Zampini         nisdofs = 1;
74641e0482f5SStefano Zampini       }
74651e0482f5SStefano Zampini     }
74666e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
746727b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
746830368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7469854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
74706e683305SStefano Zampini     /* dofs splitting */
74716e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
74726e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
74731e0482f5SStefano Zampini       if (nedcfield != i) {
74746e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
74756e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
74766e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
74776e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
74781e0482f5SStefano Zampini       } else {
74791e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
74801e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
74811e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7482eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
74831e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
74841e0482f5SStefano Zampini       }
74856e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
748630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
74876e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
74886e683305SStefano Zampini     }
74896e683305SStefano Zampini     /* neumann boundaries */
74906e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
74916e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
74926e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
74936e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
74946e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
74956e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
74966e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
749730368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
74986e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
74996e683305SStefano Zampini     }
75006e683305SStefano Zampini     /* free memory */
75016e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
75026e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
75036e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
75046e683305SStefano Zampini   } else {
75056e683305SStefano Zampini     nis = 0;
75066e683305SStefano Zampini     nisdofs = 0;
75076e683305SStefano Zampini     nisneu = 0;
750830368db7SStefano Zampini     nisvert = 0;
75096e683305SStefano Zampini     isarray = NULL;
75106e683305SStefano Zampini   }
75116e683305SStefano Zampini   /* destroy no longer needed map */
75126e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
75136e683305SStefano Zampini 
751457de7509SStefano Zampini   /* subassemble */
751557de7509SStefano Zampini   if (multilevel_allowed) {
75161ae86dd6SStefano Zampini     Vec       vp[1];
75171ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
751857de7509SStefano Zampini     PetscBool reuse,reuser;
75191ae86dd6SStefano Zampini 
752057de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
752157de7509SStefano Zampini     else reuse = PETSC_FALSE;
752257de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
75231ae86dd6SStefano Zampini     vp[0] = NULL;
75241ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
75251ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
75261ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
75271ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
75281ae86dd6SStefano Zampini       nvecs = 1;
75291ae86dd6SStefano Zampini 
75301ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7531a198735bSStefano Zampini         Mat      B,loc_divudotp;
75321ae86dd6SStefano Zampini         Vec      v,p;
75331ae86dd6SStefano Zampini         IS       dummy;
75341ae86dd6SStefano Zampini         PetscInt np;
75351ae86dd6SStefano Zampini 
7536a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7537a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
75381ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
75397dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
75401ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
75411ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
75421ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
75431ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
75441ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
75451ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
75461ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
75471ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
75481ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
75491ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
75501ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
75511ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
755274e2c79eSStefano Zampini       }
75531ae86dd6SStefano Zampini     }
75541ae86dd6SStefano Zampini     if (reuser) {
75551e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
755674e2c79eSStefano Zampini     } else {
75571e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp);CHKERRQ(ierr);
75581ae86dd6SStefano Zampini     }
75591ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
75601ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
75611ae86dd6SStefano Zampini       PetscInt    nl;
75621ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
75631ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
75641ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
75651ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
75661ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
75671ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
75681ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
75691ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7570a198735bSStefano Zampini     } else {
7571a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
75721ae86dd6SStefano Zampini     }
75731ae86dd6SStefano Zampini   } else {
75741e0482f5SStefano Zampini     ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,0,NULL,0,NULL);CHKERRQ(ierr);
75756e683305SStefano Zampini   }
757657de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
757757de7509SStefano Zampini     PetscMPIInt size;
7578f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
757957de7509SStefano Zampini     if (!multilevel_allowed) {
758057de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
75816e683305SStefano Zampini     } else {
758257de7509SStefano Zampini       Mat A;
7583779c1cceSStefano Zampini 
758457de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
758557de7509SStefano Zampini       if (coarse_mat_is) {
758657de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
758757de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
758857de7509SStefano Zampini         coarse_mat = coarse_mat_is;
758957de7509SStefano Zampini       }
759057de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
759157de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
759257de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7593779c1cceSStefano Zampini     }
7594779c1cceSStefano Zampini   }
759557de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
759657de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
75976e683305SStefano Zampini 
75986e683305SStefano Zampini   /* create local to global scatters for coarse problem */
759968457ee5SStefano Zampini   if (compute_vecs) {
76006e683305SStefano Zampini     PetscInt lrows;
76016e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
760257de7509SStefano Zampini     if (coarse_mat) {
760357de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
76046e683305SStefano Zampini     } else {
76056e683305SStefano Zampini       lrows = 0;
76066e683305SStefano Zampini     }
76076e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
76086e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
76096e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
76106e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
76116e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
76126e683305SStefano Zampini   }
76136e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7614c8587f34SStefano Zampini 
7615f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7616f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7617f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7618f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7619f9eb5b7dSStefano Zampini   } else {
7620f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7621f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7622c8587f34SStefano Zampini   }
7623c8587f34SStefano Zampini 
76246e683305SStefano Zampini   /* print some info if requested */
76256e683305SStefano Zampini   if (pcbddc->dbg_flag) {
76266e683305SStefano Zampini     if (!multilevel_allowed) {
76276e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
76286e683305SStefano Zampini       if (multilevel_requested) {
76296e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Not enough active processes on level %d (active processes %d, coarsening ratio %d)\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
76306e683305SStefano Zampini       } else if (pcbddc->max_levels) {
76316e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
76326e683305SStefano Zampini       }
76336e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
76346e683305SStefano Zampini     }
76356e683305SStefano Zampini   }
76366e683305SStefano Zampini 
76371e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
76381e0482f5SStefano Zampini   coarseG = NULL;
76391e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
76401e0482f5SStefano Zampini     MPI_Comm ccomm;
76411e0482f5SStefano Zampini     if (coarse_mat) {
76421e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
76431e0482f5SStefano Zampini     } else {
76441e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
76451e0482f5SStefano Zampini     }
76461e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
76471e0482f5SStefano Zampini   }
76481e0482f5SStefano Zampini 
7649f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
765057de7509SStefano Zampini   if (coarse_mat) {
76516a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
76526e683305SStefano Zampini     if (pcbddc->dbg_flag) {
765357de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
76546e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
76556e683305SStefano Zampini     }
7656f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7657312be037SStefano Zampini       char prefix[256],str_level[16];
7658e604994aSStefano Zampini       size_t len;
76591e0482f5SStefano Zampini 
766057de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7661422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7662c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7663f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
766457de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7665c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
76666e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7667c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
76681e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
7669c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7670e604994aSStefano Zampini       /* prefix */
7671e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7672e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7673e604994aSStefano Zampini       if (!pcbddc->current_level) {
7674e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7675e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7676c8587f34SStefano Zampini       } else {
7677e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7678312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7679312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
768034d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7681312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7682e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7683e604994aSStefano Zampini       }
7684e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
76853e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
76863e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
76873e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
76883e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7689f9eb5b7dSStefano Zampini       /* allow user customization */
7690f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
76913e3c6dadSStefano Zampini     }
76923e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
769351bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
76943e3c6dadSStefano Zampini     if (nisdofs) {
76953e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
76963e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
76973e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
76983e3c6dadSStefano Zampini       }
76993e3c6dadSStefano Zampini     }
77003e3c6dadSStefano Zampini     if (nisneu) {
77013e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
77023e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7703312be037SStefano Zampini     }
770430368db7SStefano Zampini     if (nisvert) {
770530368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
770630368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
770730368db7SStefano Zampini     }
77081e0482f5SStefano Zampini     if (coarseG) {
77091e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
77101e0482f5SStefano Zampini     }
7711f9eb5b7dSStefano Zampini 
7712f9eb5b7dSStefano Zampini     /* get some info after set from options */
7713f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7714f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
77154f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
7716b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
7717b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
7718f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7719f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7720f9eb5b7dSStefano Zampini     }
7721b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
7722b76f3995Sstefano_zampini     if (multilevel_requested && !isbddc && !isnn) {
7723b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
7724b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
7725b76f3995Sstefano_zampini       isnn   = PETSC_FALSE;
7726b76f3995Sstefano_zampini     }
772739f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
77284f3a063dSStefano Zampini     if (isredundant) {
77294f3a063dSStefano Zampini       KSP inner_ksp;
77304f3a063dSStefano Zampini       PC  inner_pc;
77319326c5c6Sstefano_zampini 
77324f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
77334f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
77344f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
77354f3a063dSStefano Zampini     }
7736f9eb5b7dSStefano Zampini 
773757de7509SStefano Zampini     /* parameters which miss an API */
773857de7509SStefano Zampini     if (isbddc) {
7739720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7740720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
774157de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
774227b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
774327b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7744a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7745a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7746a198735bSStefano Zampini         IS                     row,col;
7747a198735bSStefano Zampini         const PetscInt         *gidxs;
7748a198735bSStefano Zampini         PetscInt               n,st,M,N;
7749a198735bSStefano Zampini 
7750a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7751a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7752a198735bSStefano Zampini         st   = st-n;
7753a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7754a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7755a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7756a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7757a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7758a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7759a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7760a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7761a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7762a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7763a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7764a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7765a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7766a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7767a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7768a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7769a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7770a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7771a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7772a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
77738ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7774a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7775720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
777659e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7777720d30f9SStefano Zampini       }
7778d4d8cf7bSStefano Zampini     }
77799881197aSStefano Zampini 
77803301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
77815a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
77823301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
77833301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
77843301b35fSStefano Zampini     }
77853301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
77863301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
77873301b35fSStefano Zampini     }
77883301b35fSStefano Zampini     if (pc->pmat->spd_set) {
77893301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
77903301b35fSStefano Zampini     }
779127b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
779227b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
779327b6a85dSStefano Zampini     }
77946e683305SStefano Zampini     /* set operators */
77955f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
77966e683305SStefano Zampini     if (pcbddc->dbg_flag) {
77976e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
77986e683305SStefano Zampini     }
77996e683305SStefano Zampini   }
78001e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
78016e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7802b1ecc7b1SStefano Zampini #if 0
7803b9b85e73SStefano Zampini   {
7804b9b85e73SStefano Zampini     PetscViewer viewer;
7805b9b85e73SStefano Zampini     char filename[256];
7806b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7807b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
78086a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7809b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7810f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7811b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7812b9b85e73SStefano Zampini   }
7813b9b85e73SStefano Zampini #endif
7814f9eb5b7dSStefano Zampini 
781598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
781698a51de6SStefano Zampini     Vec crhs,csol;
781704708bb6SStefano Zampini 
7818f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7819f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7820f347579bSStefano Zampini     if (!csol) {
78212a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7822f9eb5b7dSStefano Zampini     }
7823f347579bSStefano Zampini     if (!crhs) {
78242a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7825f347579bSStefano Zampini     }
7826b0f5fe93SStefano Zampini   }
78271ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7828b0f5fe93SStefano Zampini 
7829b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7830b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7831b0f5fe93SStefano Zampini 
7832b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
78334f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
78344f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
78354f1b2e48SStefano Zampini     }
7836b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7837b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7838b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7839b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7840b0f5fe93SStefano Zampini     if (coarse_mat) {
7841b0f5fe93SStefano Zampini       Vec         nullv;
7842b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7843b0f5fe93SStefano Zampini       PetscInt    nl;
7844b0f5fe93SStefano Zampini 
7845b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7846b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7847b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7848b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7849b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7850b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7851b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7852b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7853b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7854b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7855b0f5fe93SStefano Zampini     }
7856b0f5fe93SStefano Zampini   }
7857b0f5fe93SStefano Zampini 
7858b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7859b0f5fe93SStefano Zampini     PetscBool ispreonly;
7860b0f5fe93SStefano Zampini 
7861b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7862b0f5fe93SStefano Zampini       PetscBool isnull;
7863b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7864bef83e63SStefano Zampini       if (isnull) {
7865b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7866b0f5fe93SStefano Zampini       }
7867bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7868b0f5fe93SStefano Zampini     }
7869b0f5fe93SStefano Zampini     /* setup coarse ksp */
7870b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7871cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7872cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
78736e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7874c8587f34SStefano Zampini       KSP       check_ksp;
78752b510759SStefano Zampini       KSPType   check_ksp_type;
7876c8587f34SStefano Zampini       PC        check_pc;
78776e683305SStefano Zampini       Vec       check_vec,coarse_vec;
78786a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
78792b510759SStefano Zampini       PetscInt  its;
78806e683305SStefano Zampini       PetscBool compute_eigs;
78816e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
78826e683305SStefano Zampini       PetscInt  neigs;
78838e185a42SStefano Zampini       const char *prefix;
7884c8587f34SStefano Zampini 
78852b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
78866e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7887422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
788823ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7889f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7890e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7891e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7892e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
78932b510759SStefano Zampini       if (ispreonly) {
78942b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
78956e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
78962b510759SStefano Zampini       } else {
7897cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
78986e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7899c8587f34SStefano Zampini       }
7900c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
79016e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
79026e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
79036e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7904a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7905a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7906a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7907a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7908c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7909c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7910c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7911c8587f34SStefano Zampini       /* create random vec */
79122701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7913c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
79146e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7915c8587f34SStefano Zampini       /* solve coarse problem */
79166e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7917cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
79186e683305SStefano Zampini       if (compute_eigs) {
7919854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7920854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
79216e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
79221ae86dd6SStefano Zampini         if (neigs) {
79236e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
79246e683305SStefano Zampini           lambda_min = eigs_r[0];
79256e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
79262701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
79272701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7928cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7929cbcc2c2aSStefano Zampini             }
7930c8587f34SStefano Zampini           }
7931c8587f34SStefano Zampini         }
79321ae86dd6SStefano Zampini       }
7933cbcc2c2aSStefano Zampini 
7934c8587f34SStefano Zampini       /* check coarse problem residual error */
79356e683305SStefano Zampini       if (pcbddc->dbg_flag) {
79366e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
79376e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
79386e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7939c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
79406e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
79416e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7942779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
79436e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
79446e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
79456e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
79466e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7947b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7948b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7949b0f5fe93SStefano Zampini         }
79506e683305SStefano Zampini         if (compute_eigs) {
79516e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
7952b03ebc13SStefano Zampini           KSPConvergedReason reason;
7953deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7954c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
7955b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
79566e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
7957b03ebc13SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %d iterations of %s, conv reason %d): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,reason,lambda_min,lambda_max,lambda_min_s,lambda_max_s);CHKERRQ(ierr);
79586e683305SStefano Zampini           for (i=0;i<neigs;i++) {
79596e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7960c8587f34SStefano Zampini           }
79616e683305SStefano Zampini         }
79626e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
79636e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
79646e683305SStefano Zampini       }
7965e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
79662701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7967c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
79686e683305SStefano Zampini       if (compute_eigs) {
79696e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
79706e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7971c8587f34SStefano Zampini       }
79726e683305SStefano Zampini     }
79736e683305SStefano Zampini   }
7974bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7975cbcc2c2aSStefano Zampini   /* print additional info */
7976cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
79776e683305SStefano Zampini     /* waits until all processes reaches this point */
79786e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7979cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7980cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7981cbcc2c2aSStefano Zampini   }
7982cbcc2c2aSStefano Zampini 
79832b510759SStefano Zampini   /* free memory */
7984fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7985c8587f34SStefano Zampini   PetscFunctionReturn(0);
7986c8587f34SStefano Zampini }
7987674ae819SStefano Zampini 
7988f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7989f34684f1SStefano Zampini {
7990f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7991f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7992f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7993dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7994dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
799573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7996dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7997f34684f1SStefano Zampini   PetscErrorCode ierr;
7998f34684f1SStefano Zampini 
7999f34684f1SStefano Zampini   PetscFunctionBegin;
8000f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
80016c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8002dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
80033bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8004dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8005dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
80066583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8007dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8008dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8009dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
80106c4ed002SBarry Smith   if (local_size != pcbddc->local_primal_size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %D != %D",local_size,pcbddc->local_primal_size);
8011dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8012dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8013dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8014dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8015dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8016f34684f1SStefano Zampini 
8017f34684f1SStefano Zampini   /* check numbering */
8018f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8019019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8020dc456d91SStefano Zampini     PetscInt    i;
8021b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8022f34684f1SStefano Zampini 
8023f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8024f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8025f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
80261575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8027019a44ceSStefano Zampini     /* counter */
8028019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8029019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8030019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8031019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8032019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8033019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8034f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8035f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8036727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8037f34684f1SStefano Zampini     }
8038f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8039f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8040f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8041e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8042e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8043e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8044e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8045f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8046019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8047f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8048019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
80492c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
805075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8051b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
80522c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
80532c66d082SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d (gid %d) owned by %d processes instead of %d!\n",PetscGlobalRank,i,gi,owned,neigh);CHKERRQ(ierr);
8054f34684f1SStefano Zampini       }
8055f34684f1SStefano Zampini     }
8056019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8057b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8058f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8059f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8060f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8061f34684f1SStefano Zampini     }
8062f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8063f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8064e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8065e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8066f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8067f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8068b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8069ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8070ca8b9ea9SStefano Zampini 
8071ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
80723bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8073f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8074f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8075f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8076f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
80774bc2dc4bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d,%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i],gidxs[i]);CHKERRQ(ierr);
8078f34684f1SStefano Zampini       }
8079f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8080ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8081f34684f1SStefano Zampini     }
8082f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
80831575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8084302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8085f34684f1SStefano Zampini   }
80868bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8087f34684f1SStefano Zampini   /* get back data */
8088f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8089f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8090674ae819SStefano Zampini   PetscFunctionReturn(0);
8091674ae819SStefano Zampini }
8092674ae819SStefano Zampini 
8093a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8094e456f2a8SStefano Zampini {
8095e456f2a8SStefano Zampini   IS             localis_t;
8096a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8097e456f2a8SStefano Zampini   PetscScalar    *vals;
8098e456f2a8SStefano Zampini   PetscErrorCode ierr;
8099e456f2a8SStefano Zampini 
8100e456f2a8SStefano Zampini   PetscFunctionBegin;
8101a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8102e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8103854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8104e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8105e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8106a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8107a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
81081035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
8109a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
81101035eff8SStefano Zampini   }
8111a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8112e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8113e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8114a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8115a7dc3881SStefano Zampini   /* now compute set in local ordering */
8116a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8117a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8118a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8119a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8120a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8121ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8122e456f2a8SStefano Zampini       lsize++;
8123e456f2a8SStefano Zampini     }
8124e456f2a8SStefano Zampini   }
8125854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8126a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8127ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8128e456f2a8SStefano Zampini       idxs[lsize++] = i;
8129e456f2a8SStefano Zampini     }
8130e456f2a8SStefano Zampini   }
8131a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8132a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8133e456f2a8SStefano Zampini   *localis = localis_t;
8134e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8135e456f2a8SStefano Zampini }
8136906d46d4SStefano Zampini 
813708122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8138b96c3477SStefano Zampini {
8139a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8140b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8141b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8142a64f4aa4SStefano Zampini   Mat                 S_j;
8143b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8144b96c3477SStefano Zampini   PetscBool           free_used_adj;
8145b96c3477SStefano Zampini   PetscErrorCode      ierr;
8146b96c3477SStefano Zampini 
8147b96c3477SStefano Zampini   PetscFunctionBegin;
8148b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8149b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
815008122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8151b96c3477SStefano Zampini     used_xadj = NULL;
8152b96c3477SStefano Zampini     used_adjncy = NULL;
8153b96c3477SStefano Zampini   } else {
815408122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
815508122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
815608122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
815708122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8158b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8159b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8160b96c3477SStefano Zampini     } else {
81612fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8162b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8163b96c3477SStefano Zampini       PetscInt       nvtxs;
8164b96c3477SStefano Zampini 
81652fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
81662fffb893SStefano Zampini       if (flg_row) {
8167b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8168b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8169b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8170b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
81712fffb893SStefano Zampini       } else {
81722fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
81732fffb893SStefano Zampini         used_xadj = NULL;
81742fffb893SStefano Zampini         used_adjncy = NULL;
81752fffb893SStefano Zampini       }
81762fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8177b96c3477SStefano Zampini     }
8178b96c3477SStefano Zampini   }
8179d5574798SStefano Zampini 
8180d5574798SStefano Zampini   /* setup sub_schurs data */
8181a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8182df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8183df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8184a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
818591af6908SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,NULL,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE,0,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
8186a64f4aa4SStefano Zampini   } else {
818772b8c272SStefano Zampini     Mat       change = NULL;
81889d54b7f4SStefano Zampini     Vec       scaling = NULL;
8189111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8190111315fdSstefano_zampini     PetscInt  benign_n;
8191111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8192111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8193111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8194a3df083aSStefano Zampini 
81955feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
81965feab87aSStefano Zampini       PetscInt n_vertices;
81975feab87aSStefano Zampini 
81985feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
81992034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
82005feab87aSStefano Zampini     }
820104708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
820204708bb6SStefano Zampini     if (!isseqaij) {
820304708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
820404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
820504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
820604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
820704708bb6SStefano Zampini       } else {
8208511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
820904708bb6SStefano Zampini       }
821004708bb6SStefano Zampini     }
8211a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8212a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8213ca92afb2SStefano Zampini     } else {
8214a3df083aSStefano Zampini       benign_n = 0;
8215ca92afb2SStefano Zampini     }
8216b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8217b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8218b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
821972b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
822022db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8221b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
822222db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8223b7ab4a40SStefano Zampini     }
8224b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8225b7ab4a40SStefano Zampini        We need to compute the change of basis according to the quadrature weights attached to pmat via MatSetNearNullSpace, and this could not be done (at the moment) without some hacking */
8226b7ab4a40SStefano Zampini     if (need_change) {
822788c03ad3SStefano Zampini       PC_IS   *pcisf;
822888c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
822988c03ad3SStefano Zampini       PC      pcf;
823088c03ad3SStefano Zampini 
8231e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
823288c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
823388c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
823488c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8235b9be95fcSstefano_zampini 
823688c03ad3SStefano Zampini       /* hacks */
823788c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
823872b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
823972b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
824072b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
824172b8c272SStefano Zampini       pcisf->n                     = pcis->n;
824272b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
824388c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
824488c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
824588c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
824688c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
824788c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
824888c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
824972b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
825088c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8251b9be95fcSstefano_zampini 
8252b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
825388c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
825472b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
825572b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
825672b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
825772b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8258b9be95fcSstefano_zampini 
825988c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
826072b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
826188c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
826288c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
826388c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
826488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
826588c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
826688c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8267b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
826888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
826988c03ad3SStefano Zampini     }
82709d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8271111315fdSstefano_zampini 
8272111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8273111315fdSstefano_zampini     if (iP) {
8274111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8275111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8276111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8277111315fdSstefano_zampini     }
8278111315fdSstefano_zampini     if (discrete_harmonic) {
8279111315fdSstefano_zampini       Mat A;
8280111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8281111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8282111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8283111315fdSstefano_zampini       ierr = PCBDDCSubSchursSetUp(sub_schurs,A,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal);CHKERRQ(ierr);
8284111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8285111315fdSstefano_zampini     } else {
828691af6908SStefano Zampini       ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal);CHKERRQ(ierr);
8287111315fdSstefano_zampini     }
828872b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
828972b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8290ca92afb2SStefano Zampini   }
8291d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8292b96c3477SStefano Zampini 
8293b96c3477SStefano Zampini   /* free adjacency */
8294b96c3477SStefano Zampini   if (free_used_adj) {
8295b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8296b96c3477SStefano Zampini   }
8297b96c3477SStefano Zampini   PetscFunctionReturn(0);
8298b96c3477SStefano Zampini }
8299b96c3477SStefano Zampini 
830008122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8301b96c3477SStefano Zampini {
8302b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8303b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8304b96c3477SStefano Zampini   PCBDDCGraph         graph;
8305b96c3477SStefano Zampini   PetscErrorCode      ierr;
8306b96c3477SStefano Zampini 
8307b96c3477SStefano Zampini   PetscFunctionBegin;
8308b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
830908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
83103301b35fSStefano Zampini     IS       verticesIS,verticescomm;
83113301b35fSStefano Zampini     PetscInt vsize,*idxs;
8312b96c3477SStefano Zampini 
8313b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
83143301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
83153301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
83163301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
83173301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8318c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8319b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8320be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8321441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
83223301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8323b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8324b96c3477SStefano Zampini   } else {
8325b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8326b96c3477SStefano Zampini   }
8327e4d548c7SStefano Zampini   /* print some info */
83285c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8329e4d548c7SStefano Zampini     IS       vertices;
8330e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8331c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8332e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8333e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8334e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8335e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8336e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8337e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8338e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8339e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8340e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8341c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8342e4d548c7SStefano Zampini   }
8343b96c3477SStefano Zampini 
8344b96c3477SStefano Zampini   /* sub_schurs init */
8345b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8346b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8347b334f244SStefano Zampini   }
83488b6046baSStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
8349e62b6521Sstefano_zampini   pcbddc->sub_schurs->prefix = ((PetscObject)pc)->prefix;
8350a64f4aa4SStefano Zampini 
8351b96c3477SStefano Zampini   /* free graph struct */
835208122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8353b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8354b96c3477SStefano Zampini   }
8355b96c3477SStefano Zampini   PetscFunctionReturn(0);
8356b96c3477SStefano Zampini }
8357fa34dd3eSStefano Zampini 
8358fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8359fa34dd3eSStefano Zampini {
8360fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8361fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8362fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8363fa34dd3eSStefano Zampini 
8364fa34dd3eSStefano Zampini   PetscFunctionBegin;
8365fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8366fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
83674f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8368fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
83694f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
837075c01103SStefano Zampini     PetscReal      norm;
8371fa34dd3eSStefano Zampini     PetscInt       i;
8372fa34dd3eSStefano Zampini 
8373fa34dd3eSStefano Zampini     /* B0 and B0_B */
8374fa34dd3eSStefano Zampini     if (zerodiag) {
8375fa34dd3eSStefano Zampini       IS       dummy;
8376fa34dd3eSStefano Zampini 
83774f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
83787dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8379fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8380fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8381fa34dd3eSStefano Zampini     }
8382fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8383fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8384fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8385fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8386fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8387fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8388fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8389fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8390fa34dd3eSStefano Zampini     /* S_j */
8391fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8392fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8393fa34dd3eSStefano Zampini 
8394fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8395fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8396fa34dd3eSStefano Zampini     /* continuous in primal space */
8397fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8398fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8399fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8400fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
84014f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
84024f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8403fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8404fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8405fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8406fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8407fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8408fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8409fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8410fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8411fa34dd3eSStefano Zampini 
8412fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8413fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8414fa34dd3eSStefano Zampini     /* local with Schur */
8415fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8416fa34dd3eSStefano Zampini     if (zerodiag) {
8417fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
84184f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8419fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8420fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8421fa34dd3eSStefano Zampini     }
8422fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8423fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8424fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8425fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8426fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8427fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8428fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8429fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8430fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8431fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8432fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8433fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8434fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8435fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8436fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8437fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8438fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8439fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8440fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8441fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8442fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8443fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8444fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8445fa34dd3eSStefano Zampini     if (zerodiag) {
8446fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8447fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
84484f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8449fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8450fa34dd3eSStefano Zampini     }
8451fa34dd3eSStefano Zampini     /* BDDC */
8452fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8453fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8454fa34dd3eSStefano Zampini 
8455fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8456fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8457fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8458fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
84594f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
84604f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8461fa34dd3eSStefano Zampini     }
84624f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8463fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8464fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8465fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8466fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8467fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8468fa34dd3eSStefano Zampini   }
8469fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8470fa34dd3eSStefano Zampini }
84711e0482f5SStefano Zampini 
84721e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
84731e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
84741e0482f5SStefano Zampini {
84751e0482f5SStefano Zampini   Mat            At;
84761e0482f5SStefano Zampini   IS             rows;
84771e0482f5SStefano Zampini   PetscInt       rst,ren;
84781e0482f5SStefano Zampini   PetscErrorCode ierr;
84791e0482f5SStefano Zampini   PetscLayout    rmap;
84801e0482f5SStefano Zampini 
84811e0482f5SStefano Zampini   PetscFunctionBegin;
84821e0482f5SStefano Zampini   rst = ren = 0;
84831e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
84841e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
84851e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
84861e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
84871e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
84881e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
84891e0482f5SStefano Zampini   }
8490e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
84917dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
84921e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
84931e0482f5SStefano Zampini 
84941e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
84951e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
84961e0482f5SStefano Zampini     IS         from,to;
84971e0482f5SStefano Zampini     Vec        gvec;
84981e0482f5SStefano Zampini     PetscInt   lsize;
84991e0482f5SStefano Zampini 
85001e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
85011e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
85021e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
85031e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
85041e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
85051e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
85061e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
85071e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
85081e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
85091e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
85101e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
85111e0482f5SStefano Zampini     b->A = a->A;
85121e0482f5SStefano Zampini     b->B = a->B;
85131e0482f5SStefano Zampini 
85141e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
85151e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
85161e0482f5SStefano Zampini     b->rowindices      = 0;
85171e0482f5SStefano Zampini     b->rowvalues       = 0;
85181e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
85191e0482f5SStefano Zampini 
85201e0482f5SStefano Zampini     (*B)->rmap         = rmap;
85211e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
85221e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
85231e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
85241e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
85251e0482f5SStefano Zampini 
85261e0482f5SStefano Zampini     if (a->colmap) {
85271e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
85281e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
85291e0482f5SStefano Zampini #else
85301e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
85311e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
85321e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
85331e0482f5SStefano Zampini #endif
85341e0482f5SStefano Zampini     } else b->colmap = 0;
85351e0482f5SStefano Zampini     if (a->garray) {
85361e0482f5SStefano Zampini       PetscInt len;
85371e0482f5SStefano Zampini       len  = a->B->cmap->n;
85381e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
85391e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
85401e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
85411e0482f5SStefano Zampini     } else b->garray = 0;
85421e0482f5SStefano Zampini 
85431e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
85441e0482f5SStefano Zampini     b->lvec = a->lvec;
85451e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
85461e0482f5SStefano Zampini 
85471e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
85481e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
85491e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
85501e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
85511e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
85521e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
85531e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
85541e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
85551e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
85561e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
85571e0482f5SStefano Zampini   }
85581e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
85591e0482f5SStefano Zampini   PetscFunctionReturn(0);
85601e0482f5SStefano Zampini }
8561