xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision a040e873671ad20e30a5bf9be2cdefa367590b3b)
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>
4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h>
5c80a6c00SStefano Zampini #include <petscdmplex.h>
6674ae819SStefano Zampini #include <petscblaslapack.h>
7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h>
97620a527SStefano Zampini #include <petscdmda.h>
10674ae819SStefano Zampini 
111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
121e0482f5SStefano Zampini 
13f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
14f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
16a13144ffSStefano Zampini {
17a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
18a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
19a13144ffSStefano Zampini   PetscReal      *sing;
20a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
21a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
22a13144ffSStefano Zampini   PetscErrorCode ierr;
23a13144ffSStefano Zampini 
24a13144ffSStefano Zampini   PetscFunctionBegin;
25a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
26a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
27614dbb09SStefano Zampini #else
28a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
29a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
30a13144ffSStefano Zampini 
31a13144ffSStefano Zampini   /* workspace */
32a13144ffSStefano Zampini   if (!work) {
33a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
34f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
35a13144ffSStefano Zampini   } else {
36a13144ffSStefano Zampini     ulw   = lw;
37a13144ffSStefano Zampini     uwork = work;
38a13144ffSStefano Zampini   }
39a13144ffSStefano Zampini   n = PetscMin(nr,nc);
40a13144ffSStefano Zampini   if (!rwork) {
41a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
42a13144ffSStefano Zampini   } else {
43a13144ffSStefano Zampini     sing = rwork;
44a13144ffSStefano Zampini   }
45a13144ffSStefano Zampini 
46a13144ffSStefano Zampini   /* SVD */
47a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
55a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
56a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
57a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
58a13144ffSStefano Zampini   if (!rwork) {
59a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   if (!work) {
62a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
63a13144ffSStefano Zampini   }
64a13144ffSStefano Zampini   /* create B */
65f498cd09SStefano Zampini   if (!range) {
66a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
67a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
68a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
69f498cd09SStefano Zampini   } else {
70f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
71f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
72f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
73f498cd09SStefano Zampini   }
74a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
75a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
76614dbb09SStefano Zampini #endif
77614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
78a13144ffSStefano Zampini   PetscFunctionBegin;
79a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
80a13144ffSStefano Zampini #endif
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1237dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
156a13144ffSStefano Zampini {
157a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
158a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1590569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
160eee23b56SStefano Zampini   Vec                    tvec;
161a13144ffSStefano Zampini   PetscSF                sfv;
1621e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
163a13144ffSStefano Zampini   MPI_Comm               comm;
164c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
165c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1667d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
167a13144ffSStefano Zampini   PetscScalar            *vals,*work;
168a13144ffSStefano Zampini   PetscReal              *rwork;
169a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1701e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
171a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
172eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
173b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
174a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
175b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
176637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
177b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179b03ebc13SStefano Zampini #endif
180213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
181a13144ffSStefano Zampini   PetscErrorCode         ierr;
182a13144ffSStefano Zampini 
183a13144ffSStefano Zampini   PetscFunctionBegin;
184213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
185213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
186213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
187213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
188213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
189213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
190213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
191213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
192a13144ffSStefano Zampini   print      = PETSC_FALSE;
193213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
194a13144ffSStefano Zampini 
195213b8bfaSStefano Zampini   /* Command line customization */
196213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
201213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
202213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203213b8bfaSStefano Zampini 
204213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2051e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2061e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   if (!singular) {
209a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
210a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
211c2151214SStefano Zampini     for (i=0;i<n;i++) {
212a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
213a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
214a13144ffSStefano Zampini         break;
215a13144ffSStefano Zampini       }
216a13144ffSStefano Zampini     }
217a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
219a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
220213b8bfaSStefano Zampini   }
221a13144ffSStefano Zampini 
222213b8bfaSStefano Zampini   /* Get Nedelec field */
223213b8bfaSStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
224c2151214SStefano 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);
225213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
226c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
227c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
228c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
229213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
230213b8bfaSStefano Zampini     ne            = n;
231213b8bfaSStefano Zampini     nedfieldlocal = NULL;
232213b8bfaSStefano Zampini     global        = PETSC_TRUE;
233213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
234213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
235213b8bfaSStefano Zampini 
236213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
237213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
238213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
239213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
240213b8bfaSStefano Zampini       PetscInt nc;
241213b8bfaSStefano Zampini 
242213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
243213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
244213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
245213b8bfaSStefano Zampini     }
246213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
248213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
249213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
250213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
251213b8bfaSStefano Zampini   } else {
252213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
253213b8bfaSStefano Zampini   }
254213b8bfaSStefano Zampini 
255213b8bfaSStefano Zampini   /* Sanity checks */
256213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
257213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
258213b8bfaSStefano 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);
259213b8bfaSStefano Zampini 
260213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2611e0482f5SStefano Zampini   if (setprimal) {
262eee23b56SStefano Zampini     IS       enedfieldlocal;
263eee23b56SStefano Zampini     PetscInt *eidxs;
264eee23b56SStefano Zampini 
265eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
266eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
267213b8bfaSStefano Zampini     if (nedfieldlocal) {
268213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
269eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
270eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
271eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
272eee23b56SStefano Zampini         }
273eee23b56SStefano Zampini       }
274eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
275213b8bfaSStefano Zampini     } else {
276213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
277213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
278213b8bfaSStefano Zampini           eidxs[cum++] = i;
279213b8bfaSStefano Zampini         }
280213b8bfaSStefano Zampini       }
281213b8bfaSStefano Zampini     }
282213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
285eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
287eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2881e0482f5SStefano Zampini     PetscFunctionReturn(0);
2891e0482f5SStefano Zampini   }
290a13144ffSStefano Zampini 
291213b8bfaSStefano Zampini   /* Compute some l2g maps */
292213b8bfaSStefano Zampini   if (nedfieldlocal) {
293c2151214SStefano Zampini     IS is;
294c2151214SStefano Zampini 
295c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
296c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2981e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2991e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
3001e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
3011e0482f5SStefano Zampini     if (global) {
3021e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3031e0482f5SStefano Zampini       el2g = al2g;
3041e0482f5SStefano Zampini     } else {
3051e0482f5SStefano Zampini       IS gis;
3061e0482f5SStefano Zampini 
3071e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3081e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3091e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3101e0482f5SStefano Zampini     }
311c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
312c2151214SStefano Zampini   } else {
3131e0482f5SStefano Zampini     /* restore default */
3141e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3151e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3161e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3171e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3181e0482f5SStefano Zampini     el2g = al2g;
319c2151214SStefano Zampini     fl2g = NULL;
320c2151214SStefano Zampini   }
321a13144ffSStefano Zampini 
322213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
323c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
324c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
325c2151214SStefano Zampini   if (nedfieldlocal) {
326c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
328c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
329c2151214SStefano Zampini   } else {
330c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
331c2151214SStefano Zampini   }
332c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
334213b8bfaSStefano Zampini 
335213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
336213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
337213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     if (global) {
3391e0482f5SStefano Zampini       PetscInt rst;
3401e0482f5SStefano Zampini 
341c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
342c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
343c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
344c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
345c2151214SStefano Zampini         }
346c2151214SStefano Zampini       }
347a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
348c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3491e0482f5SStefano Zampini     } else {
3501e0482f5SStefano Zampini       PetscInt *tbz;
3511e0482f5SStefano Zampini 
3521e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3561e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3571e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3581e0482f5SStefano Zampini           tbz[cum++] = i;
3591e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3621e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3631e0482f5SStefano Zampini     }
364213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
365213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
366213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
367213b8bfaSStefano Zampini   }
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3727dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
378a13144ffSStefano Zampini 
379213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
380c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
387a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
388213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
389213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
390a13144ffSStefano Zampini 
3911e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
392213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
393a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
394213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
395a13144ffSStefano Zampini 
396213b8bfaSStefano Zampini   if (print) {
397213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
398213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
399213b8bfaSStefano Zampini   }
400213b8bfaSStefano Zampini 
401213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4020569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4030569b399SStefano Zampini 
404a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4054e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4064e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4107d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
411c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
412a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
413a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
414a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
415c2151214SStefano Zampini     IS is;
416c2151214SStefano Zampini 
417c2151214SStefano Zampini     if (fl2g) {
418c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
419c2151214SStefano Zampini     } else {
420c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
421c2151214SStefano Zampini     }
422c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
423c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
424a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
425a13144ffSStefano Zampini       if (idxs[i] >= 0) {
426a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4277d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
428a13144ffSStefano Zampini       }
429a13144ffSStefano Zampini     }
430c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
431c2151214SStefano Zampini     if (fl2g) {
432c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
433c2151214SStefano Zampini     }
434a13144ffSStefano Zampini   }
435a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
436c2151214SStefano Zampini     IS is;
437c2151214SStefano Zampini 
438c2151214SStefano Zampini     if (fl2g) {
439c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
440c2151214SStefano Zampini     } else {
441c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
442c2151214SStefano Zampini     }
443c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
444c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
445a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
446a13144ffSStefano Zampini       if (idxs[i] >= 0) {
447a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
448a13144ffSStefano Zampini       }
449a13144ffSStefano Zampini     }
450c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
451c2151214SStefano Zampini     if (fl2g) {
452c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
453a13144ffSStefano Zampini     }
454c2151214SStefano Zampini   }
455c2151214SStefano Zampini 
456213b8bfaSStefano Zampini   /* Count neighs per dof */
457637e8532SStefano Zampini   ierr = PetscCalloc1(ne,&ecount);CHKERRQ(ierr);
458637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&eneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
460637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
461637e8532SStefano Zampini     cum += n_shared[i];
462637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
463637e8532SStefano Zampini       ecount[shared[i][j]]++;
464637e8532SStefano Zampini     }
465637e8532SStefano Zampini   }
466637e8532SStefano Zampini   if (ne) {
467637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&eneighs[0]);CHKERRQ(ierr);
468637e8532SStefano Zampini   }
469637e8532SStefano Zampini   for (i=1;i<ne;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
470637e8532SStefano Zampini   ierr = PetscMemzero(ecount,ne*sizeof(PetscInt));CHKERRQ(ierr);
471637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
472637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
473637e8532SStefano Zampini       PetscInt k = shared[i][j];
474637e8532SStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
475637e8532SStefano Zampini       ecount[k]++;
476637e8532SStefano Zampini     }
477637e8532SStefano Zampini   }
478637e8532SStefano Zampini   for (i=0;i<ne;i++) {
479637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr);
480637e8532SStefano Zampini   }
481637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
482637e8532SStefano Zampini   ierr = PetscCalloc1(nv,&vcount);CHKERRQ(ierr);
483637e8532SStefano Zampini   ierr = PetscMalloc1(nv,&vneighs);CHKERRQ(ierr);
484637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
485637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
486637e8532SStefano Zampini     cum += n_shared[i];
487637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
488637e8532SStefano Zampini       vcount[shared[i][j]]++;
489637e8532SStefano Zampini     }
490637e8532SStefano Zampini   }
491637e8532SStefano Zampini   if (nv) {
492637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&vneighs[0]);CHKERRQ(ierr);
493637e8532SStefano Zampini   }
494637e8532SStefano Zampini   for (i=1;i<nv;i++) vneighs[i] = vneighs[i-1] + vcount[i-1];
495637e8532SStefano Zampini   ierr = PetscMemzero(vcount,nv*sizeof(PetscInt));CHKERRQ(ierr);
496637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
497637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
498637e8532SStefano Zampini       PetscInt k = shared[i][j];
499637e8532SStefano Zampini       vneighs[k][vcount[k]] = neigh[i];
500637e8532SStefano Zampini       vcount[k]++;
501637e8532SStefano Zampini     }
502637e8532SStefano Zampini   }
503637e8532SStefano Zampini   for (i=0;i<nv;i++) {
504637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&vcount[i],vneighs[i]);CHKERRQ(ierr);
505637e8532SStefano Zampini   }
506637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
507637e8532SStefano Zampini 
5087d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
5097d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
51062b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
5127d871cd7SStefano Zampini     if ((ecount[i] > 1 && !PetscBTLookup(btbd,i)) || (ecount[i] == 1 && PetscBTLookup(btb,i))) {
51362b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
51462b0c6f7SStefano Zampini     }
51562b0c6f7SStefano Zampini   }
516637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
51762b0c6f7SStefano Zampini   if (!conforming) {
51862b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
51962b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52062b0c6f7SStefano Zampini   }
5214e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
52362b0c6f7SStefano Zampini   cum  = 0;
524a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
525dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
52662b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
527a13144ffSStefano Zampini       marks[cum++] = i;
528dec27d64SStefano Zampini       continue;
529dec27d64SStefano Zampini     }
530dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
53162b0c6f7SStefano Zampini     if (!conforming) {
53262b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
533a13144ffSStefano Zampini         marks[cum++] = i;
534a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
535a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
536a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
537a13144ffSStefano Zampini         }
53862b0c6f7SStefano Zampini       } else {
53962b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
54062b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
54162b0c6f7SStefano Zampini            - at most 2 endpoints
54262b0c6f7SStefano Zampini            - order-1 interior nodal dofs
54362b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
54462b0c6f7SStefano Zampini         */
54562b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
54662b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
54762b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
54862b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
54962b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
55062b0c6f7SStefano Zampini           if (nconn > order) ends++;
55162b0c6f7SStefano Zampini           else if (nconn == order) ints++;
55262b0c6f7SStefano Zampini           else undef++;
55362b0c6f7SStefano Zampini         }
55462b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
55562b0c6f7SStefano Zampini           marks[cum++] = i;
55662b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
55762b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
55862b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
55962b0c6f7SStefano Zampini           }
56062b0c6f7SStefano Zampini         }
56162b0c6f7SStefano Zampini       }
562a13144ffSStefano Zampini     }
563dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
564dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
565dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
566dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
567a13144ffSStefano Zampini     }
568dec27d64SStefano Zampini   }
56962b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
570dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5714e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
57262b0c6f7SStefano Zampini   if (!conforming) {
57362b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
57462b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
57562b0c6f7SStefano Zampini   }
5764e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
577637e8532SStefano Zampini 
578b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5794e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
580a13144ffSStefano Zampini   if (print) {
5814e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5824e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5834e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
584a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
585a13144ffSStefano Zampini   }
586a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
587dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
588a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
589637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5907d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
591b03ebc13SStefano Zampini     if (!order) { /* variable order */
592dec27d64SStefano Zampini       PetscReal vorder = 0.;
593dec27d64SStefano Zampini 
594dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
595dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
596dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
597dec27d64SStefano Zampini       ord  = 1;
598dec27d64SStefano Zampini     }
599a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
600dec27d64SStefano 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);
601a13144ffSStefano Zampini #endif
602637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
6037d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
6047d871cd7SStefano Zampini         bdir = PETSC_TRUE;
6057d871cd7SStefano Zampini         break;
6067d871cd7SStefano Zampini       }
607637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
608637e8532SStefano Zampini         sneighs = PETSC_FALSE;
609637e8532SStefano Zampini       } else {
610637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
611637e8532SStefano Zampini         for (k=0;k<vc;k++) {
612637e8532SStefano Zampini           if (vn[k] != en[k]) {
613637e8532SStefano Zampini             sneighs = PETSC_FALSE;
614637e8532SStefano Zampini             break;
615637e8532SStefano Zampini           }
616637e8532SStefano Zampini         }
617637e8532SStefano Zampini       }
618637e8532SStefano Zampini     }
6197d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
6207d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
621a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
622dec27d64SStefano Zampini     } else if (test == ord) {
623b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
624a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
625a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
626a13144ffSStefano Zampini       } else {
627a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
628a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
629a13144ffSStefano Zampini       }
630a13144ffSStefano Zampini     }
631a13144ffSStefano Zampini   }
632637e8532SStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
633637e8532SStefano Zampini   ierr = PetscFree(vcount);CHKERRQ(ierr);
634637e8532SStefano Zampini   if (ne) {
635637e8532SStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
636637e8532SStefano Zampini   }
637637e8532SStefano Zampini   if (nv) {
638637e8532SStefano Zampini     ierr = PetscFree(vneighs[0]);CHKERRQ(ierr);
639637e8532SStefano Zampini   }
640637e8532SStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
641637e8532SStefano Zampini   ierr = PetscFree(vneighs);CHKERRQ(ierr);
6427d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
643b03ebc13SStefano Zampini 
644b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
645b03ebc13SStefano Zampini   if (order != 1) {
646b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
647b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
648b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
649b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
650b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
651b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
652b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
653b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
654b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
655b03ebc13SStefano Zampini             PetscInt v = jjt[k];
656b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
657b03ebc13SStefano Zampini               found = PETSC_TRUE;
658b03ebc13SStefano Zampini               break;
659b03ebc13SStefano Zampini             }
660b03ebc13SStefano Zampini           }
661b03ebc13SStefano Zampini         }
662b03ebc13SStefano Zampini         if (!found) {
663b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
664b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
665b03ebc13SStefano Zampini         } else {
666b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
667b03ebc13SStefano Zampini         }
668b03ebc13SStefano Zampini       }
669b03ebc13SStefano Zampini     }
670b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
671b03ebc13SStefano Zampini   }
672dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
673a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
674b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
675a13144ffSStefano Zampini 
676a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6770569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
678a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6794e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
680a13144ffSStefano Zampini 
6814e64d54eSstefano_zampini   /* Mark interior nodal dofs */
682a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6834e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
684a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
685a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6864e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
687a13144ffSStefano Zampini     }
688a13144ffSStefano Zampini   }
689a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
690a13144ffSStefano Zampini 
691a13144ffSStefano Zampini   /* communicate corners and splitpoints */
692a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
693a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
694a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
695a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
696a13144ffSStefano Zampini 
697a13144ffSStefano Zampini   if (print) {
698a13144ffSStefano Zampini     IS tbz;
699a13144ffSStefano Zampini 
700a13144ffSStefano Zampini     cum = 0;
701a13144ffSStefano Zampini     for (i=0;i<nv;i++)
702a13144ffSStefano Zampini       if (sfvleaves[i])
703a13144ffSStefano Zampini         vmarks[cum++] = i;
704a13144ffSStefano Zampini 
705a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
706a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
707a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
708a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
709a13144ffSStefano Zampini   }
710a13144ffSStefano Zampini 
711a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
712a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
713a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
715a13144ffSStefano Zampini 
7164e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
7174e64d54eSstefano_zampini      and interior nodal dofs */
718a13144ffSStefano Zampini   cum = 0;
719a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
720a13144ffSStefano Zampini     if (sfvleaves[i]) {
721a13144ffSStefano Zampini       vmarks[cum++] = i;
722a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
723a13144ffSStefano Zampini     }
7244e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
725a13144ffSStefano Zampini   }
7264e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
727a13144ffSStefano Zampini   if (print) {
728a13144ffSStefano Zampini     IS tbz;
729a13144ffSStefano Zampini 
730a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
7314e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
732a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
733a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
734a13144ffSStefano Zampini   }
735a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
736a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
737a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
738a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
739a13144ffSStefano Zampini 
740a13144ffSStefano Zampini   /* Recompute G */
741a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
742a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
743a13144ffSStefano Zampini   if (print) {
744a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
745a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
746a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
747a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
748a13144ffSStefano Zampini   }
749a13144ffSStefano Zampini 
750a13144ffSStefano Zampini   /* Get primal dofs (if any) */
751a13144ffSStefano Zampini   cum = 0;
752a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
753a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
754a13144ffSStefano Zampini   }
755c2151214SStefano Zampini   if (fl2g) {
756c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
757c2151214SStefano Zampini   }
758a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
759a13144ffSStefano Zampini   if (print) {
760a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
761a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
762a13144ffSStefano Zampini   }
763a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
764c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
765a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
766a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
767a13144ffSStefano Zampini 
768a13144ffSStefano Zampini   /* Compute edge connectivity */
769a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
770a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
771a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
772c2151214SStefano Zampini   if (fl2g) {
773c2151214SStefano Zampini     PetscBT   btf;
774c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
775c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
776c2151214SStefano Zampini 
777c2151214SStefano Zampini     /* create CSR for all local dofs */
778c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
779c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
780c2151214SStefano 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);
781c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
782c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
783c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
784c2151214SStefano Zampini       rest = PETSC_TRUE;
785c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
786c2151214SStefano Zampini     } else {
787c2151214SStefano Zampini       free   = PETSC_TRUE;
788c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
789c2151214SStefano Zampini       iiu[0] = 0;
790c2151214SStefano Zampini       for (i=0;i<n;i++) {
791c2151214SStefano Zampini         iiu[i+1] = i+1;
792c2151214SStefano Zampini         jju[i]   = -1;
793d904f53bSStefano Zampini       }
794c2151214SStefano Zampini     }
795c2151214SStefano Zampini 
796c2151214SStefano Zampini     /* import sizes of CSR */
797c2151214SStefano Zampini     iia[0] = 0;
798c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
799c2151214SStefano Zampini 
800c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
801c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
802c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
803c2151214SStefano Zampini     for (i=0;i<ne;i++) {
804c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
805c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
806c2151214SStefano Zampini     }
807c2151214SStefano Zampini 
808c2151214SStefano Zampini     /* iia in CSR */
809c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
810c2151214SStefano Zampini 
811c2151214SStefano Zampini     /* jja in CSR */
812c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
813c2151214SStefano Zampini     for (i=0;i<n;i++)
814c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
815c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
816c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
817c2151214SStefano Zampini 
818c2151214SStefano Zampini     /* map edge dofs connectivity */
8191e0482f5SStefano Zampini     if (jj) {
820c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
821c2151214SStefano Zampini       for (i=0;i<ne;i++) {
822c2151214SStefano Zampini         PetscInt e = idxs[i];
823c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
824c2151214SStefano Zampini       }
8251e0482f5SStefano Zampini     }
826c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
827c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
828c2151214SStefano Zampini     if (rest) {
829c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
830c2151214SStefano Zampini     }
831c2151214SStefano Zampini     if (free) {
832c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
833c2151214SStefano Zampini     }
834c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
835c2151214SStefano Zampini   } else {
836c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
837c2151214SStefano Zampini   }
838c2151214SStefano Zampini 
839a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
840a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
841213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
842a13144ffSStefano Zampini 
843a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
844c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
845a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
846a13144ffSStefano Zampini 
847c2151214SStefano Zampini   if (fl2g) {
848c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
849c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
850c2151214SStefano Zampini     for (i=0;i<nee;i++) {
851c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
852c2151214SStefano Zampini     }
853c2151214SStefano Zampini   } else {
854c2151214SStefano Zampini     eedges  = alleedges;
855c2151214SStefano Zampini     primals = allprimals;
856c2151214SStefano Zampini   }
857c2151214SStefano Zampini 
858a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
859a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
860c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
861c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
862c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
863c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
864c2151214SStefano Zampini   if (print) {
865c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
866c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
867c2151214SStefano Zampini   }
868c2151214SStefano Zampini 
869c2151214SStefano Zampini   maxsize = 0;
870a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
871a13144ffSStefano Zampini     PetscInt size,mark = i+1;
872a13144ffSStefano Zampini 
873a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
874a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
876a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
878a13144ffSStefano Zampini   }
879a13144ffSStefano Zampini 
880a13144ffSStefano Zampini   /* Find coarse edge endpoints */
881a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
882a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
883a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
884a13144ffSStefano Zampini     PetscInt mark = i+1,size;
885a13144ffSStefano Zampini 
886a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8871e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8881e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
889a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
890a13144ffSStefano Zampini     if (print) {
891a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
892a13144ffSStefano Zampini       ISView(eedges[i],NULL);
893a13144ffSStefano Zampini     }
894a13144ffSStefano Zampini     for (j=0;j<size;j++) {
895a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
896a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
897a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
898a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
899a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
900a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
901a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
902a13144ffSStefano Zampini           PetscInt  k2;
903a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
904a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
905c2151214SStefano 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]));
906c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
907c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
908c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
909a13144ffSStefano Zampini               corner = PETSC_TRUE;
910a13144ffSStefano Zampini               break;
911a13144ffSStefano Zampini             }
912a13144ffSStefano Zampini           }
913a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
914a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
915a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
916a13144ffSStefano Zampini           } else {
917a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
918a13144ffSStefano Zampini           }
919a13144ffSStefano Zampini         }
920a13144ffSStefano Zampini       }
921a13144ffSStefano Zampini     }
922a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
923a13144ffSStefano Zampini   }
924a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
925a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
926c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
927a13144ffSStefano Zampini 
928a13144ffSStefano Zampini   /* Reset marked primal dofs */
929a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
930a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
931a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
932a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
933a13144ffSStefano Zampini 
9340569b399SStefano Zampini   /* Now use the initial lG */
9350569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
9360569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
9370569b399SStefano Zampini   lG   = lGinit;
9380569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
9390569b399SStefano Zampini 
940a13144ffSStefano Zampini   /* Compute extended cols indices */
941b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
942b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
943a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
945a13144ffSStefano Zampini   i   *= maxsize;
946b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
947a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
948a13144ffSStefano Zampini   eerr = PETSC_FALSE;
949a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
950b03ebc13SStefano Zampini     PetscInt size,found = 0;
951a13144ffSStefano Zampini 
952a13144ffSStefano Zampini     cum  = 0;
953a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9541e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9551e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
956a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
957b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
958a13144ffSStefano Zampini     for (j=0;j<size;j++) {
959a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
960b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
961b03ebc13SStefano Zampini         PetscInt vv = jj[k];
962b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
963b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
964b03ebc13SStefano Zampini       }
965a13144ffSStefano Zampini     }
966a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
967a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
968a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
969a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
970a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
971a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
972a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
973b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
974b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
975a13144ffSStefano Zampini       if (print) {
976a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
977a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
978a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
979a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
980a13144ffSStefano Zampini       }
981a13144ffSStefano Zampini       eerr = PETSC_TRUE;
982a13144ffSStefano Zampini     }
983a13144ffSStefano Zampini   }
9844e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
985a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
986a13144ffSStefano Zampini   if (done) {
987a13144ffSStefano Zampini     PetscInt *newprimals;
988a13144ffSStefano Zampini 
989a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
990a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
991a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
992a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
993a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9940569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
995b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
996a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
997b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
998b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
999a13144ffSStefano Zampini         PetscInt size,mark = i+1;
1000a13144ffSStefano Zampini 
1001a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1002a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1003c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
1004a13144ffSStefano Zampini         for (j=0;j<size;j++) {
1005a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
1006b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
1007a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1008a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
1009a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
1010a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
1011b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
1012b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
1013a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
1014a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
1015a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
1016a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
1017a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
1018b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
1019a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
1020a13144ffSStefano Zampini                   /* finally set the new corners */
1021a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
1022b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
1023a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
1024a13144ffSStefano Zampini                   }
1025a13144ffSStefano Zampini                 }
1026a13144ffSStefano Zampini               }
1027b03ebc13SStefano Zampini             } else {
1028b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
1029a13144ffSStefano Zampini             }
1030a13144ffSStefano Zampini           }
1031a13144ffSStefano Zampini         }
1032b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
1033b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
1034b03ebc13SStefano Zampini 
1035b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
1036b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
1037b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1038b03ebc13SStefano Zampini             PetscInt k2;
1039b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
1040b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
1041b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
1042b03ebc13SStefano Zampini           }
1043b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
1044b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
1045b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
1046b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
1047b03ebc13SStefano Zampini             }
1048b03ebc13SStefano Zampini           }
1049b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
1050b03ebc13SStefano Zampini         }
1051a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1052a13144ffSStefano Zampini       }
1053a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1054a13144ffSStefano Zampini     }
1055b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10560569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1057a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1058c2151214SStefano Zampini     if (fl2g) {
1059c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1060c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1061c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1062c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1063c2151214SStefano Zampini       }
1064c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1065c2151214SStefano Zampini     }
1066c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1067a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1068a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1069a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1070a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1071a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1072213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1073c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1074c2151214SStefano Zampini     if (fl2g) {
1075c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1076c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1077c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1078c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1079c2151214SStefano Zampini       }
1080c2151214SStefano Zampini     } else {
1081c2151214SStefano Zampini       eedges  = alleedges;
1082c2151214SStefano Zampini       primals = allprimals;
1083c2151214SStefano Zampini     }
1084b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1085a13144ffSStefano Zampini 
1086a13144ffSStefano Zampini     /* Mark again */
1087a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1088a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1089a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1090a13144ffSStefano Zampini 
1091a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1092a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1093a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1094a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095a13144ffSStefano Zampini     }
1096a13144ffSStefano Zampini     if (print) {
1097a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1098a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1099a13144ffSStefano Zampini     }
1100a13144ffSStefano Zampini 
1101a13144ffSStefano Zampini     /* Recompute extended cols */
1102a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1103a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1104a13144ffSStefano Zampini       PetscInt size;
1105a13144ffSStefano Zampini 
1106a13144ffSStefano Zampini       cum  = 0;
1107a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11081e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
11091e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1110a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1111a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1112a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
11131e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1114a13144ffSStefano Zampini       }
1115a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1116a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1117a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1118a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1119a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1120a13144ffSStefano Zampini       if (cum != size -1) {
1121a13144ffSStefano Zampini         if (print) {
1122a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1123a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1124a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1125a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1126a13144ffSStefano Zampini         }
1127a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1128a13144ffSStefano Zampini       }
1129a13144ffSStefano Zampini     }
1130a13144ffSStefano Zampini   }
1131a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1132a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1133b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
11347d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1135a13144ffSStefano Zampini   /* an error should not occur at this point */
1136a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1137a13144ffSStefano Zampini 
11384e64d54eSstefano_zampini   /* Check the number of endpoints */
11390569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1140b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1141b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
11424e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1143b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
11444e64d54eSstefano_zampini 
1145b03ebc13SStefano Zampini     /* init with defaults */
1146b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
11474e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11481e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
11491e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
11504e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1151b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11524e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11534e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11544e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11554e64d54eSstefano_zampini         PetscInt vv = jj[k];
11564e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1157b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1158b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11594e64d54eSstefano_zampini         }
11604e64d54eSstefano_zampini       }
11614e64d54eSstefano_zampini     }
1162b03ebc13SStefano Zampini     if (found != 2) {
1163b03ebc13SStefano Zampini       PetscInt e;
1164b03ebc13SStefano Zampini       if (fl2g) {
1165b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1166b03ebc13SStefano Zampini       } else {
1167b03ebc13SStefano Zampini         e = idxs[0];
1168b03ebc13SStefano Zampini       }
1169b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1170b03ebc13SStefano Zampini     }
1171eee23b56SStefano Zampini 
1172eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1173b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1174b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1175b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1176b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1177b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1178b03ebc13SStefano Zampini     }
1179eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11804e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1181b03ebc13SStefano 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]);
11824e64d54eSstefano_zampini   }
11830569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11844e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11854e64d54eSstefano_zampini 
1186a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1187a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1188a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1189a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1190a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1191a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1192a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1193a13144ffSStefano Zampini 
1194a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1195a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1196a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1197a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1198a13144ffSStefano Zampini       if (emax < emarks[j]) {
1199a13144ffSStefano Zampini         emax = emarks[j];
1200a13144ffSStefano Zampini         eemax = j;
1201a13144ffSStefano Zampini       }
1202a13144ffSStefano Zampini     }
1203a13144ffSStefano Zampini     /* not relevant for edges */
1204a13144ffSStefano Zampini     if (!eemax) continue;
1205a13144ffSStefano Zampini 
1206a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1207a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1208c2151214SStefano 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]);
1209a13144ffSStefano Zampini       }
1210a13144ffSStefano Zampini     }
1211a13144ffSStefano Zampini   }
1212a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1214a13144ffSStefano Zampini #endif
1215a13144ffSStefano Zampini 
1216a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1217a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   extmem *= maxsize;
1220a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1222a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1223a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1224a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1225213b8bfaSStefano Zampini 
1226a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1227a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1228a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1229a13144ffSStefano Zampini         mark = marks[jj[j]];
1230a13144ffSStefano Zampini 
1231a13144ffSStefano Zampini     /* not relevant */
1232a13144ffSStefano Zampini     if (!mark) continue;
1233a13144ffSStefano Zampini 
1234a13144ffSStefano Zampini     /* import extended row */
1235a13144ffSStefano Zampini     mark--;
1236a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1237a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1238a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1239a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1240a13144ffSStefano Zampini     extrowcum[mark] += size;
1241a13144ffSStefano Zampini   }
1242a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1243213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1244213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1245213b8bfaSStefano Zampini 
1246213b8bfaSStefano Zampini   /* Compress extrows */
1247a13144ffSStefano Zampini   cum  = 0;
1248a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1249a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1250a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1251a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1252a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1253a13144ffSStefano Zampini   }
1254a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1255a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1256a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1257a13144ffSStefano Zampini 
1258a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1259a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1260a13144ffSStefano Zampini 
1261a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1262a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1263c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1264c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1265a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1266a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1267a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12681e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1269a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1270a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1271213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1272a13144ffSStefano Zampini 
1273a13144ffSStefano Zampini   /* Defaults to identity */
1274c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1275a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1276a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1277a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1278a13144ffSStefano Zampini 
12791e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12801e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12811e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12821e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12831e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12841e0482f5SStefano Zampini     IS                     wis,gwis;
12851e0482f5SStefano Zampini     PetscInt               cnv,cne;
12861e0482f5SStefano Zampini 
12871e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12881e0482f5SStefano Zampini     if (fl2g) {
12891e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12901e0482f5SStefano Zampini     } else {
12911e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12921e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12931e0482f5SStefano Zampini     }
12941e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12951e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12961e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12971e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12981e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12991e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
13021e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
13031e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13041e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
13051e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
13061e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13071e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13081e0482f5SStefano Zampini 
13091e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
13101e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
13111e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
13121e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
13141e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
13151e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
13161e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
13171e0482f5SStefano Zampini   }
1318213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
13191e0482f5SStefano Zampini 
13201e0482f5SStefano Zampini #if defined(PRINT_GDET)
13211e0482f5SStefano Zampini   inc = 0;
13221e0482f5SStefano Zampini   lev = pcbddc->current_level;
13231e0482f5SStefano Zampini #endif
1324213b8bfaSStefano Zampini 
1325213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1326a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1327a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
13281e0482f5SStefano Zampini     IS          cornersis = NULL;
13291e0482f5SStefano Zampini     PetscScalar cvals[2];
1330a13144ffSStefano Zampini 
13311e0482f5SStefano Zampini     if (pcbddc->nedcG) {
13321e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
13331e0482f5SStefano Zampini     }
13341e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1335a13144ffSStefano Zampini     if (Gins && GKins) {
1336a13144ffSStefano Zampini       PetscScalar    *data;
1337a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1338a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1339a13144ffSStefano Zampini 
1340a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1341a13144ffSStefano Zampini       /* H1 */
1342a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1343a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1344a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1345a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1346a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1347a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1348a13144ffSStefano Zampini       /* complement */
1349a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
13501e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1351213b8bfaSStefano 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);
1352213b8bfaSStefano 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);
1353a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1354a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1355a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13561e0482f5SStefano Zampini 
13571e0482f5SStefano Zampini       /* coarse discrete gradient */
13581e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13591e0482f5SStefano Zampini         PetscInt cols[2];
13601e0482f5SStefano Zampini 
13611e0482f5SStefano Zampini         cols[0] = 2*i;
13621e0482f5SStefano Zampini         cols[1] = 2*i+1;
13631e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13641e0482f5SStefano Zampini       }
1365a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1366a13144ffSStefano Zampini     }
1367a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1368a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13691e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1370a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1371a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1372a13144ffSStefano Zampini   }
1373213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1374a13144ffSStefano Zampini 
1375a13144ffSStefano Zampini   /* Start assembling */
1376a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13771e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13781e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13791e0482f5SStefano Zampini   }
1380a13144ffSStefano Zampini 
1381a13144ffSStefano Zampini   /* Free */
1382c2151214SStefano Zampini   if (fl2g) {
1383c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1384c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1385c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1386c2151214SStefano Zampini     }
1387c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1388c2151214SStefano Zampini   }
1389eee23b56SStefano Zampini 
1390eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1391eee23b56SStefano Zampini   {
1392eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1393eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1394eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1395eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1396eee23b56SStefano Zampini 
1397eee23b56SStefano Zampini     /* find first primal edge */
1398eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1399eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1400eee23b56SStefano Zampini     } else {
1401eee23b56SStefano Zampini       if (fl2g) {
1402eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1403eee23b56SStefano Zampini       }
1404eee23b56SStefano Zampini       idxs = cedges;
1405eee23b56SStefano Zampini     }
1406eee23b56SStefano Zampini     cum = 0;
1407eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1408eee23b56SStefano Zampini 
1409eee23b56SStefano Zampini     /* adapt connected components */
1410eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1411eee23b56SStefano Zampini     graph->cptr[0] = 0;
1412eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1413eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1414eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1415eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1416eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1417eee23b56SStefano Zampini         ncc++;
1418eee23b56SStefano Zampini         lc--;
1419eee23b56SStefano Zampini         cum++;
1420eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1421eee23b56SStefano Zampini       }
1422eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1423eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1424eee23b56SStefano Zampini       ncc++;
1425eee23b56SStefano Zampini     }
1426eee23b56SStefano Zampini     graph->ncc = ncc;
1427eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1428eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1429eee23b56SStefano Zampini     }
1430eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1431eee23b56SStefano Zampini   }
1432213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1433c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1434c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1435213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1436eee23b56SStefano Zampini 
1437c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1438a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1439a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1440b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1441b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1442a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1443a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1444a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1445a13144ffSStefano Zampini 
1446a13144ffSStefano Zampini   /* Complete assembling */
1447a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14481e0482f5SStefano Zampini   if (pcbddc->nedcG) {
14491e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14501e0482f5SStefano Zampini #if 0
14511e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14521e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14531e0482f5SStefano Zampini #endif
14541e0482f5SStefano Zampini   }
1455a13144ffSStefano Zampini 
1456a13144ffSStefano Zampini   /* set change of basis */
1457213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1458a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1459a13144ffSStefano Zampini 
1460a13144ffSStefano Zampini   PetscFunctionReturn(0);
1461a13144ffSStefano Zampini }
1462a13144ffSStefano Zampini 
1463d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1464d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1465d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1466d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1467d8203eabSStefano Zampini {
1468d8203eabSStefano Zampini   PetscErrorCode ierr;
1469d8203eabSStefano Zampini   PetscInt       i;
1470d8203eabSStefano Zampini 
1471d8203eabSStefano Zampini   PetscFunctionBegin;
1472d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1473d8203eabSStefano Zampini     PetscInt first,last;
1474d8203eabSStefano Zampini 
1475d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
147686fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1477d8203eabSStefano Zampini     if (i>=first && i < last) {
1478d8203eabSStefano Zampini       PetscScalar *data;
1479d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1480d8203eabSStefano Zampini       if (!has_const) {
1481d8203eabSStefano Zampini         data[i-first] = 1.;
1482d8203eabSStefano Zampini       } else {
148386fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
148486fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1485d8203eabSStefano Zampini       }
1486d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1487d8203eabSStefano Zampini     }
1488d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1489d8203eabSStefano Zampini   }
1490d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1491d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1492d8203eabSStefano Zampini     PetscInt first,last;
1493ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1494d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1495d8203eabSStefano Zampini     if (i>=first && i < last) {
1496d8203eabSStefano Zampini       PetscScalar *data;
1497d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1498d8203eabSStefano Zampini       if (!has_const) {
1499d8203eabSStefano Zampini         data[i-first] = 0.;
1500d8203eabSStefano Zampini       } else {
150186fa73c5SStefano Zampini         data[2*i-first] = 0.;
150286fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1503d8203eabSStefano Zampini       }
1504d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1505d8203eabSStefano Zampini     }
1506d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1507ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1508d8203eabSStefano Zampini   }
1509d8203eabSStefano Zampini   PetscFunctionReturn(0);
1510d8203eabSStefano Zampini }
1511d8203eabSStefano Zampini 
15128ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1513669cc0f4SStefano Zampini {
1514a198735bSStefano Zampini   Mat                    loc_divudotp;
1515fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
15168ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1517669cc0f4SStefano Zampini   PetscScalar            *vals;
1518669cc0f4SStefano Zampini   const PetscScalar      *array;
1519*a040e873SStefano Zampini   PetscInt               i,maxneighs,maxsize;
1520*a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
15211ae86dd6SStefano Zampini   PetscMPIInt            rank;
1522a198735bSStefano Zampini   PetscErrorCode         ierr;
1523669cc0f4SStefano Zampini 
1524669cc0f4SStefano Zampini   PetscFunctionBegin;
1525*a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1526*a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1527669cc0f4SStefano Zampini   maxsize = 0;
1528*a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
1529669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1530669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1531669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
15328ae0ca82SStefano Zampini   if (!transpose) {
15338ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
15348ae0ca82SStefano Zampini   } else {
15358ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
15368ae0ca82SStefano Zampini   }
1537669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
15381ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1539d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1540669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1541ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
15428ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini   }
1544d8203eabSStefano Zampini 
1545669cc0f4SStefano Zampini   /* compute local quad vec */
1546a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15478ae0ca82SStefano Zampini   if (!transpose) {
1548a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15498ae0ca82SStefano Zampini   } else {
15508ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15518ae0ca82SStefano Zampini   }
1552669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15538ae0ca82SStefano Zampini   if (!transpose) {
1554a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15558ae0ca82SStefano Zampini   } else {
15568ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15578ae0ca82SStefano Zampini   }
1558fa23a32eSStefano Zampini   if (vl2l) {
1559187c917aSStefano Zampini     Mat        lA;
1560187c917aSStefano Zampini     VecScatter sc;
1561187c917aSStefano Zampini 
1562187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1563187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
1564187c917aSStefano Zampini     ierr = VecScatterCreate(v,vl2l,vins,NULL,&sc);CHKERRQ(ierr);
1565187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1566187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1567187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1568fa23a32eSStefano Zampini   } else {
1569fa23a32eSStefano Zampini     vins = v;
1570fa23a32eSStefano Zampini   }
1571fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1572669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15739a962809SStefano Zampini 
15741ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15751ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1576*a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) {
1577669cc0f4SStefano Zampini     const PetscInt    *idxs;
1578669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1579669cc0f4SStefano Zampini 
1580*a040e873SStefano Zampini     idxs = shared[i];
1581*a040e873SStefano Zampini     nn   = n_shared[i];
1582669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15831ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1584669cc0f4SStefano Zampini     idx  = -(idx+1);
1585669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1586669cc0f4SStefano Zampini   }
1587*a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1588fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1589fa23a32eSStefano Zampini   if (vl2l) {
1590187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1591fa23a32eSStefano Zampini   }
1592669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1593669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1594669cc0f4SStefano Zampini 
1595669cc0f4SStefano Zampini   /* assemble near null space */
1596669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1597669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1598669cc0f4SStefano Zampini   }
1599669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1600669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1601ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1602669cc0f4SStefano Zampini   }
1603669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1604669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1605669cc0f4SStefano Zampini }
1606669cc0f4SStefano Zampini 
16077620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
16087620a527SStefano Zampini {
16097620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16107620a527SStefano Zampini   PetscErrorCode ierr;
16117620a527SStefano Zampini 
16127620a527SStefano Zampini   PetscFunctionBegin;
16137620a527SStefano Zampini   if (primalv) {
16147620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
16157620a527SStefano Zampini       IS list[2], newp;
16167620a527SStefano Zampini 
16177620a527SStefano Zampini       list[0] = primalv;
16187620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
16197620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
16207620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
16217620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
16227620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
16237620a527SStefano Zampini     } else {
16247620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
16257620a527SStefano Zampini     }
16267620a527SStefano Zampini   }
16277620a527SStefano Zampini   PetscFunctionReturn(0);
16287620a527SStefano Zampini }
1629669cc0f4SStefano Zampini 
16301f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
16311f4df5f7SStefano Zampini {
16321f4df5f7SStefano Zampini   PetscErrorCode ierr;
16331f4df5f7SStefano Zampini   Vec            local,global;
16341f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16351f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
16365c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
16371f4df5f7SStefano Zampini 
16381f4df5f7SStefano Zampini   PetscFunctionBegin;
16395c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
16405c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16415c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16421f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
164321ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16441f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16456a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16466a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16476a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16486a8fc67bSStefano Zampini     }
16496a8fc67bSStefano Zampini     goto boundary;
16506a8fc67bSStefano Zampini   }
16515c5e10d6SStefano Zampini 
16521f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16531f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16541f4df5f7SStefano Zampini       PetscInt i;
16551f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16561f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16571f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16581f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16591f4df5f7SStefano Zampini       }
16601f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16611f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16621f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16631f4df5f7SStefano Zampini     }
16641f4df5f7SStefano Zampini   } else {
166521ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
166621ef3d20SStefano Zampini       DM dm;
166721ef3d20SStefano Zampini 
166821ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
166921ef3d20SStefano Zampini       if (!dm) {
167021ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
167121ef3d20SStefano Zampini       }
167221ef3d20SStefano Zampini       if (dm) {
167321ef3d20SStefano Zampini         IS      *fields;
167421ef3d20SStefano Zampini         PetscInt nf,i;
167521ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
167621ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
167721ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
167821ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
167921ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
168021ef3d20SStefano Zampini         }
168121ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
168221ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
168321ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
168421ef3d20SStefano Zampini         PetscContainer   c;
168521ef3d20SStefano Zampini 
168621ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
168721ef3d20SStefano Zampini         if (c) {
168821ef3d20SStefano Zampini           MatISLocalFields lf;
168921ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
169021ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
169121ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16921f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1693986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
169421ef3d20SStefano Zampini           if (i > 1) {
1695986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16961f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16971f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16981f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16991f4df5f7SStefano Zampini             }
17001f4df5f7SStefano Zampini           }
170121ef3d20SStefano Zampini         }
170221ef3d20SStefano Zampini       }
17037a0e7b2cSstefano_zampini     } else {
17047a0e7b2cSstefano_zampini       PetscInt i;
17057a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
17067a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
17077a0e7b2cSstefano_zampini       }
17081f4df5f7SStefano Zampini     }
1709986cdee1SStefano Zampini   }
17101f4df5f7SStefano Zampini 
17115c5e10d6SStefano Zampini boundary:
17121f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
17131f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17147a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
17157a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17161f4df5f7SStefano Zampini   }
17171f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
17181f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17197a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
17207a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17211f4df5f7SStefano Zampini   }
17221f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
17231f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
17241f4df5f7SStefano Zampini   }
17251f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
17261f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
17277620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
17287620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
17297620a527SStefano Zampini     IS       primalv = NULL;
17307620a527SStefano Zampini     PetscInt i;
17317a0e7b2cSstefano_zampini 
17327620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17337620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17347620a527SStefano Zampini     }
17357620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17367620a527SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17377620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17387620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17397620a527SStefano Zampini   }
17407620a527SStefano Zampini   /* early stage corner detection */
17417620a527SStefano Zampini   {
17427620a527SStefano Zampini     DM dm;
17437620a527SStefano Zampini 
17447620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17457620a527SStefano Zampini     if (dm) {
17467620a527SStefano Zampini       PetscBool isda;
17477620a527SStefano Zampini 
17487620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17497620a527SStefano Zampini       if (isda) {
17507620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17517620a527SStefano Zampini         IS                     corners;
17527620a527SStefano Zampini         Mat                    lA;
17537620a527SStefano Zampini 
1754d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17557620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17567620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17577620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17587620a527SStefano Zampini         if (l2l) {
17597620a527SStefano Zampini           const PetscInt *idx;
17607620a527SStefano Zampini           PetscInt       bs,*idxout,n;
17617620a527SStefano Zampini 
17627620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17637620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17647620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
17657620a527SStefano Zampini           ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17667620a527SStefano Zampini           ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
17677620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1768d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17697620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17707620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17717620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17727620a527SStefano Zampini         } else { /* not from DMDA */
1773d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17747620a527SStefano Zampini         }
17757620a527SStefano Zampini       }
17767620a527SStefano Zampini     }
17777620a527SStefano Zampini   }
17787a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
17797a0e7b2cSstefano_zampini }
17807a0e7b2cSstefano_zampini 
17817a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
17827a0e7b2cSstefano_zampini {
17837a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
17847a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
17857a0e7b2cSstefano_zampini   IS              nis;
17867a0e7b2cSstefano_zampini   const PetscInt  *idxs;
17877a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
17887a0e7b2cSstefano_zampini   PetscBool       *ld;
17897a0e7b2cSstefano_zampini 
17907a0e7b2cSstefano_zampini   PetscFunctionBegin;
17917a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
17927a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
17937a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
17947a0e7b2cSstefano_zampini     /* init rootdata with true */
17957a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
17967a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
17977a0e7b2cSstefano_zampini   } else {
17987a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
17997a0e7b2cSstefano_zampini   }
18007a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18017a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18027a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18037a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18047a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18057a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18067a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18077a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18087a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18097a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18107a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18117a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18127a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18137a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18147a0e7b2cSstefano_zampini   } else {
18157a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18167a0e7b2cSstefano_zampini   }
18177a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18187a0e7b2cSstefano_zampini     if (ld[i])
18197a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18207a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18217a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18227a0e7b2cSstefano_zampini   *is  = nis;
18231f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18241f4df5f7SStefano Zampini }
18251f4df5f7SStefano Zampini 
18263e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18273e589ea0SStefano Zampini {
18283e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18293e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18303e589ea0SStefano Zampini   PetscErrorCode    ierr;
18313e589ea0SStefano Zampini 
18323e589ea0SStefano Zampini   PetscFunctionBegin;
18333e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18343e589ea0SStefano Zampini     PetscFunctionReturn(0);
18353e589ea0SStefano Zampini   }
18363e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18373e589ea0SStefano Zampini     Vec swap;
18383e589ea0SStefano Zampini 
18393e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18403e589ea0SStefano Zampini     swap = pcbddc->work_change;
18413e589ea0SStefano Zampini     pcbddc->work_change = r;
18423e589ea0SStefano Zampini     r = swap;
18433e589ea0SStefano Zampini   }
18443e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18453e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18463e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18473e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18483e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18493e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18503e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1851f913dca9SStefano Zampini     pcbddc->work_change = r;
18523e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18533e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18543e589ea0SStefano Zampini   }
18553e589ea0SStefano Zampini   PetscFunctionReturn(0);
18563e589ea0SStefano Zampini }
18573e589ea0SStefano Zampini 
1858a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1859a3df083aSStefano Zampini {
1860a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1861a3df083aSStefano Zampini   PetscErrorCode          ierr;
1862a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1863a3df083aSStefano Zampini 
1864a3df083aSStefano Zampini   PetscFunctionBegin;
1865a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1866a3df083aSStefano Zampini   if (transpose) {
1867a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1868a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1869a3df083aSStefano Zampini   } else {
1870a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1871a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1872a3df083aSStefano Zampini   }
1873a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1874a3df083aSStefano Zampini   if (apply_right) {
1875a3df083aSStefano Zampini     const PetscScalar *ax;
1876a3df083aSStefano Zampini     PetscInt          nl,i;
1877a3df083aSStefano Zampini 
1878a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1879a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1880a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1881a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1882a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1883a3df083aSStefano Zampini       PetscScalar    sum,val;
1884a3df083aSStefano Zampini       const PetscInt *idxs;
1885a3df083aSStefano Zampini       PetscInt       nz,j;
1886a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1887a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1888a3df083aSStefano Zampini       sum = 0.;
1889a3df083aSStefano Zampini       if (ctx->apply_p0) {
1890a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1891a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1892a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1893a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1894a3df083aSStefano Zampini         }
1895a3df083aSStefano Zampini       } else {
1896a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1897a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1898a3df083aSStefano Zampini         }
1899a3df083aSStefano Zampini       }
1900a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1901a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1902a3df083aSStefano Zampini     }
1903a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1904a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1905a3df083aSStefano Zampini   }
1906a3df083aSStefano Zampini   if (transpose) {
1907a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1908a3df083aSStefano Zampini   } else {
1909a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1910a3df083aSStefano Zampini   }
1911a3df083aSStefano Zampini   if (reset_x) {
1912a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1913a3df083aSStefano Zampini   }
1914a3df083aSStefano Zampini   if (apply_left) {
1915a3df083aSStefano Zampini     PetscScalar *ay;
1916a3df083aSStefano Zampini     PetscInt    i;
1917a3df083aSStefano Zampini 
1918a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1919a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1920a3df083aSStefano Zampini       PetscScalar    sum,val;
1921a3df083aSStefano Zampini       const PetscInt *idxs;
1922a3df083aSStefano Zampini       PetscInt       nz,j;
1923a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1924a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1925a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1926a3df083aSStefano Zampini       if (ctx->apply_p0) {
1927a3df083aSStefano Zampini         sum = 0.;
1928a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1929a3df083aSStefano Zampini           sum += ay[idxs[j]];
1930a3df083aSStefano Zampini           ay[idxs[j]] += val;
1931a3df083aSStefano Zampini         }
1932a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1933a3df083aSStefano Zampini       } else {
1934a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1935a3df083aSStefano Zampini           ay[idxs[j]] += val;
1936a3df083aSStefano Zampini         }
1937a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1938a3df083aSStefano Zampini       }
1939a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1940a3df083aSStefano Zampini     }
1941a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1942a3df083aSStefano Zampini   }
1943a3df083aSStefano Zampini   PetscFunctionReturn(0);
1944a3df083aSStefano Zampini }
1945a3df083aSStefano Zampini 
1946a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1947a3df083aSStefano Zampini {
1948a3df083aSStefano Zampini   PetscErrorCode ierr;
1949a3df083aSStefano Zampini 
1950a3df083aSStefano Zampini   PetscFunctionBegin;
1951a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1952a3df083aSStefano Zampini   PetscFunctionReturn(0);
1953a3df083aSStefano Zampini }
1954a3df083aSStefano Zampini 
1955a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1956a3df083aSStefano Zampini {
1957a3df083aSStefano Zampini   PetscErrorCode ierr;
1958a3df083aSStefano Zampini 
1959a3df083aSStefano Zampini   PetscFunctionBegin;
1960a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1961a3df083aSStefano Zampini   PetscFunctionReturn(0);
1962a3df083aSStefano Zampini }
1963a3df083aSStefano Zampini 
1964a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1965a3df083aSStefano Zampini {
1966a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1967a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1968a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1969a3df083aSStefano Zampini   PetscErrorCode          ierr;
1970a3df083aSStefano Zampini 
1971a3df083aSStefano Zampini   PetscFunctionBegin;
1972a3df083aSStefano Zampini   if (!restore) {
19731dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1974a3df083aSStefano Zampini     PetscScalar        *work;
1975b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1976a3df083aSStefano Zampini 
19779a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
19789a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1979a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1980a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1981a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1982a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1983a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1984a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1985a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1986a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1987a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1988a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1989a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1990a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1991059032f7SStefano Zampini     if (reuse) {
1992a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
19931dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1994059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1995059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1996059032f7SStefano Zampini       PetscInt               i;
1997059032f7SStefano Zampini 
1998059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1999059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2000059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2001059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2002059032f7SStefano Zampini       }
2003059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20041dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2005059032f7SStefano Zampini     }
2006a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2007a3df083aSStefano Zampini     ctx->work = work;
2008a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2009a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2010a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2011a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2012a3df083aSStefano Zampini 
2013a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2014a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2015a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2016a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2017a3df083aSStefano Zampini   } else {
20181dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20191dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20201dd7afcfSStefano Zampini     }
2021a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2022a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2023a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20241dd7afcfSStefano Zampini     ctx->A = NULL;
20251dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20261dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20271dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20281dd7afcfSStefano Zampini     if (ctx->free) {
2029059032f7SStefano Zampini       PetscInt i;
20301dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2031059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2032059032f7SStefano Zampini       }
2033059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2034059032f7SStefano Zampini     }
2035a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2036a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2037a3df083aSStefano Zampini   }
2038a3df083aSStefano Zampini   PetscFunctionReturn(0);
2039a3df083aSStefano Zampini }
2040a3df083aSStefano Zampini 
2041a3df083aSStefano Zampini /* used just in bddc debug mode */
2042a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2043a3df083aSStefano Zampini {
2044a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2045a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2046a3df083aSStefano Zampini   Mat            An;
2047a3df083aSStefano Zampini   PetscErrorCode ierr;
2048a3df083aSStefano Zampini 
2049a3df083aSStefano Zampini   PetscFunctionBegin;
2050a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2051a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2052a3df083aSStefano Zampini   if (is1) {
20537dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2054a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2055a3df083aSStefano Zampini   } else {
2056a3df083aSStefano Zampini     *B = An;
2057a3df083aSStefano Zampini   }
2058a3df083aSStefano Zampini   PetscFunctionReturn(0);
2059a3df083aSStefano Zampini }
2060a3df083aSStefano Zampini 
20611cf9b237SStefano Zampini /* TODO: add reuse flag */
20621cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20631cf9b237SStefano Zampini {
20641cf9b237SStefano Zampini   Mat            Bt;
20651cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20661cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20671cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20681cf9b237SStefano Zampini   PetscBool      flg_row;
20691cf9b237SStefano Zampini   PetscErrorCode ierr;
20701cf9b237SStefano Zampini 
20711cf9b237SStefano Zampini   PetscFunctionBegin;
20721cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20731cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20741cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20751cf9b237SStefano Zampini   nnz = n;
20761cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20771cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
20781cf9b237SStefano Zampini   }
20791cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
20801cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
20811cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
20821cf9b237SStefano Zampini   nnz = 0;
20831cf9b237SStefano Zampini   bii[0] = 0;
20841cf9b237SStefano Zampini   for (i=0;i<n;i++) {
20851cf9b237SStefano Zampini     PetscInt j;
20861cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
20871cf9b237SStefano Zampini       PetscScalar entry = a[j];
20881cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
20891cf9b237SStefano Zampini         bij[nnz] = ij[j];
20901cf9b237SStefano Zampini         bdata[nnz] = entry;
20911cf9b237SStefano Zampini         nnz++;
20921cf9b237SStefano Zampini       }
20931cf9b237SStefano Zampini     }
20941cf9b237SStefano Zampini     bii[i+1] = nnz;
20951cf9b237SStefano Zampini   }
20961cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
20971cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
20981cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20991cf9b237SStefano Zampini   {
21001cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21011cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21021cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21031cf9b237SStefano Zampini   }
21041cf9b237SStefano Zampini   *B = Bt;
21051cf9b237SStefano Zampini   PetscFunctionReturn(0);
21061cf9b237SStefano Zampini }
21071cf9b237SStefano Zampini 
2108c80a6c00SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscInt *ncc, IS* cc[], IS* primalv)
21094f1b2e48SStefano Zampini {
2110c80a6c00SStefano Zampini   Mat                    B = NULL;
2111c80a6c00SStefano Zampini   DM                     dm;
21124f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21134f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21144f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2115c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21164f1b2e48SStefano Zampini   PetscInt               i,n;
21174f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2118c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21194f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21204f1b2e48SStefano Zampini 
21214f1b2e48SStefano Zampini   PetscFunctionBegin;
2122a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2123a2eca866SStefano Zampini   if (cc) *cc = NULL;
2124a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2125c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2126c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2127c80a6c00SStefano Zampini   if (!dm) {
2128c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2129c80a6c00SStefano Zampini   }
2130c80a6c00SStefano Zampini   if (dm) {
2131c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2132c80a6c00SStefano Zampini   }
2133c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2134c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2135c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2136c80a6c00SStefano Zampini     IS             cellNumbering;
2137c80a6c00SStefano Zampini     const PetscInt *cellNum;
2138c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2139c80a6c00SStefano Zampini     PetscSection   section;
2140c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2141c80a6c00SStefano Zampini     PetscSF        sfPoint;
2142c80a6c00SStefano Zampini     PetscErrorCode ierr;
2143c80a6c00SStefano Zampini 
2144c80a6c00SStefano Zampini     PetscFunctionBegin;
2145c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2146c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2147c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2148c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2149c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2150c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2151c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2152c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2153c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2154c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2155c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2156c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2157956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2158c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2159c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2160c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2161c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2162c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2163c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2164c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2165c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21665cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2167c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2168c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2169c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2170c80a6c00SStefano Zampini           *pBuf = point;
2171c80a6c00SStefano Zampini         }
2172c80a6c00SStefano Zampini       }
2173c80a6c00SStefano Zampini       n++;
2174c80a6c00SStefano Zampini     }
2175c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2176c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2177c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2178c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2179c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2180c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2181c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2182c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2183c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2184c80a6c00SStefano Zampini     }
2185c80a6c00SStefano Zampini     xadj[n] = size;
2186c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2187c80a6c00SStefano Zampini     /* Clean up */
2188c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2189c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2190c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2191c80a6c00SStefano Zampini     graph->xadj = xadj;
2192c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2193c80a6c00SStefano Zampini   } else {
2194c80a6c00SStefano Zampini     Mat       A;
2195c80a6c00SStefano Zampini     PetscBool filter = PETSC_FALSE, isseqaij, flg_row;
2196c80a6c00SStefano Zampini 
2197c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
219863c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2199a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
220063c961adSStefano Zampini       PetscFunctionReturn(0);
220163c961adSStefano Zampini     }
22024f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22034f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22041cf9b237SStefano Zampini       PetscBool isseqdense;
22051cf9b237SStefano Zampini 
22061cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22071cf9b237SStefano Zampini       if (!isseqdense) {
22084f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22091cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22101cf9b237SStefano Zampini         PetscScalar *array;
22111cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22121cf9b237SStefano Zampini 
22131cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22141cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22151cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22161cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22171cf9b237SStefano Zampini           PetscInt j;
22181cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22191cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22201cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22211cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22221cf9b237SStefano Zampini           }
22231cf9b237SStefano Zampini         }
22241cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22259d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22261cf9b237SStefano Zampini       }
22274f1b2e48SStefano Zampini     } else {
2228c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22294f1b2e48SStefano Zampini       B = A;
22304f1b2e48SStefano Zampini     }
22314f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22324f1b2e48SStefano Zampini 
22334f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22344f1b2e48SStefano Zampini     if (filter) {
22354f1b2e48SStefano Zampini       PetscScalar *data;
22364f1b2e48SStefano Zampini       PetscInt    j,cum;
22374f1b2e48SStefano Zampini 
22384f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22394f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22404f1b2e48SStefano Zampini       cum = 0;
22414f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22424f1b2e48SStefano Zampini         PetscInt t;
22434f1b2e48SStefano Zampini 
22444f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22454f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22464f1b2e48SStefano Zampini             continue;
22474f1b2e48SStefano Zampini           }
22484f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22494f1b2e48SStefano Zampini         }
22504f1b2e48SStefano Zampini         t = xadj_filtered[i];
22514f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22524f1b2e48SStefano Zampini         cum += t;
22534f1b2e48SStefano Zampini       }
22544f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22554f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22564f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22574f1b2e48SStefano Zampini     } else {
22584f1b2e48SStefano Zampini       graph->xadj = xadj;
22594f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22604f1b2e48SStefano Zampini     }
2261c80a6c00SStefano Zampini   }
2262c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2263c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2264c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2265c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2266c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2267c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22684f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22694f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2270c80a6c00SStefano Zampini 
22714f1b2e48SStefano Zampini   /* partial clean up */
22724f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2273c80a6c00SStefano Zampini   if (B) {
2274c80a6c00SStefano Zampini     PetscBool flg_row;
22754f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22764f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
22774f1b2e48SStefano Zampini   }
2278c80a6c00SStefano Zampini   if (isplex) {
2279c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2280c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2281c80a6c00SStefano Zampini   }
22824f1b2e48SStefano Zampini 
22834f1b2e48SStefano Zampini   /* get back data */
2284c80a6c00SStefano Zampini   if (isplex) {
2285c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2286c80a6c00SStefano Zampini     if (cc || primalv) {
2287c80a6c00SStefano Zampini       Mat          A;
2288c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2289c80a6c00SStefano Zampini       PetscSection subSection;
2290c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2291c80a6c00SStefano Zampini 
2292c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2293c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2294c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2295c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2296c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2297c80a6c00SStefano Zampini 
2298c80a6c00SStefano Zampini       cids[0] = 0;
2299c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2300c80a6c00SStefano Zampini         PetscInt j;
2301c80a6c00SStefano Zampini 
2302c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2303c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2304c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2305c80a6c00SStefano Zampini 
2306c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2307c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2308c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2309c80a6c00SStefano Zampini 
2310c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2311c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2312c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2313c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2314c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2315c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2316c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2317c80a6c00SStefano Zampini               } else { /* cross-vertex */
2318c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2319c80a6c00SStefano Zampini               }
2320c80a6c00SStefano Zampini             }
2321c80a6c00SStefano Zampini           }
2322c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2323c80a6c00SStefano Zampini         }
2324c80a6c00SStefano Zampini         cids[i+1] = cum;
2325c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2326c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2327c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2328c80a6c00SStefano Zampini         }
2329c80a6c00SStefano Zampini       }
2330c80a6c00SStefano Zampini       if (cc) {
2331c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2332c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2333c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2334c80a6c00SStefano Zampini         }
2335c80a6c00SStefano Zampini         *cc = cc_n;
2336c80a6c00SStefano Zampini       }
2337c80a6c00SStefano Zampini       if (primalv) {
2338c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2339c80a6c00SStefano Zampini       }
2340c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2341c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2342c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2343c80a6c00SStefano Zampini     }
2344c80a6c00SStefano Zampini   } else {
23451cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23461cf9b237SStefano Zampini     if (cc) {
23474f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23484f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23494f1b2e48SStefano 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);
23504f1b2e48SStefano Zampini       }
23514f1b2e48SStefano Zampini       *cc = cc_n;
23521cf9b237SStefano Zampini     }
2353c80a6c00SStefano Zampini   }
23544f1b2e48SStefano Zampini   /* clean up graph */
23554f1b2e48SStefano Zampini   graph->xadj = 0;
23564f1b2e48SStefano Zampini   graph->adjncy = 0;
23574f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23584f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23594f1b2e48SStefano Zampini }
23604f1b2e48SStefano Zampini 
23615408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23625408967cSStefano Zampini {
23635408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23645408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2365dee84bffSStefano Zampini   IS             dirIS = NULL;
23664f1b2e48SStefano Zampini   PetscInt       i;
23675408967cSStefano Zampini   PetscErrorCode ierr;
23685408967cSStefano Zampini 
23695408967cSStefano Zampini   PetscFunctionBegin;
2370dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
23715408967cSStefano Zampini   if (zerodiag) {
23725408967cSStefano Zampini     Mat            A;
23735408967cSStefano Zampini     Vec            vec3_N;
23745408967cSStefano Zampini     PetscScalar    *vals;
23755408967cSStefano Zampini     const PetscInt *idxs;
2376d12d3064SStefano Zampini     PetscInt       nz,*count;
23775408967cSStefano Zampini 
23785408967cSStefano Zampini     /* p0 */
23795408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
23805408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
23815408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
23825408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
23834f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
23845408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23855408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
23865408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
23875408967cSStefano Zampini     /* v_I */
23885408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
23895408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
23905408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23915408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
23925408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
23935408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
23945408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23955408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
23965408967cSStefano Zampini     if (dirIS) {
23975408967cSStefano Zampini       PetscInt n;
23985408967cSStefano Zampini 
23995408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24005408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24015408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24025408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24035408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24045408967cSStefano Zampini     }
24055408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24065408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24075408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24085408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2409669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24105408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24115408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24129a962809SStefano 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]));
24135408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24145408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2415d12d3064SStefano Zampini 
2416d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2417d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2418d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2419d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2420d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2421d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24229a962809SStefano 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]);
2423d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2424d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24255408967cSStefano Zampini   }
2426dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24275408967cSStefano Zampini 
24285408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24295408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24304f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24315408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24324f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24335408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2434f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2435f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
243613903a91SSatish Balay     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);
2437f2a566d8SStefano Zampini   }
24385408967cSStefano Zampini   PetscFunctionReturn(0);
24395408967cSStefano Zampini }
24405408967cSStefano Zampini 
2441339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2442339f8db1SStefano Zampini {
2443339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24444edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2445b0f5fe93SStefano Zampini   PetscInt       nz,n;
24464edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24474edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2448339f8db1SStefano Zampini   PetscErrorCode ierr;
2449339f8db1SStefano Zampini 
2450339f8db1SStefano Zampini   PetscFunctionBegin;
24519f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24529f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2453a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2454a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2455a3df083aSStefano Zampini   }
2456a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2457a3df083aSStefano Zampini   pcbddc->benign_n = 0;
245828b8efb1Sstefano_zampini 
245928b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
24604f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
24614f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24624f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24631ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24644f1b2e48SStefano Zampini   */
24654f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
24664f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
246740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24687fbe2174Sstefano_zampini     IS       iP = NULL;
24694f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
24704f1b2e48SStefano Zampini 
247128b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
247228b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
247328b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
247428b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
24754f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
24764f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
24774f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24784f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2479ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24807fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
24817fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
24827fbe2174Sstefano_zampini     if (iP) {
24837fbe2174Sstefano_zampini       IS newpressures;
24847fbe2174Sstefano_zampini 
24857fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
24867fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
24877fbe2174Sstefano_zampini       pressures = newpressures;
24887fbe2174Sstefano_zampini     }
248940fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
249040fa8d13SStefano Zampini     if (!sorted) {
249140fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
249240fa8d13SStefano Zampini     }
249340fa8d13SStefano Zampini   } else {
249440fa8d13SStefano Zampini     pressures = NULL;
249540fa8d13SStefano Zampini   }
249697d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
249797d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
249827b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
249997d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2500339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2501339f8db1SStefano Zampini   if (!sorted) {
2502339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2503339f8db1SStefano Zampini   }
25044edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25054edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2506339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25074f1b2e48SStefano Zampini   if (!nz) {
25084f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25094f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
251040fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
251140fa8d13SStefano Zampini   }
25124f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25134f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25144f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25154f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
25161f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25171f4df5f7SStefano Zampini   interior_dofs    = NULL;
25184edc6404Sstefano_zampini   nneu             = 0;
25194edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25204edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25214edc6404Sstefano_zampini   }
25223369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25234edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25241f4df5f7SStefano Zampini     PetscInt n,i,j;
25251f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25261f4df5f7SStefano Zampini     PetscInt *iwork;
25271f4df5f7SStefano Zampini 
25281f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25291f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25301f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25311f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
253290648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25331f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25341f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25351f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25361f4df5f7SStefano Zampini       if (!iwork[i])
25371f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25381f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25391f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25401f4df5f7SStefano Zampini   }
25414f1b2e48SStefano Zampini   if (has_null_pressures) {
25424f1b2e48SStefano Zampini     IS             *subs;
25434edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
25441f4df5f7SStefano Zampini     const PetscInt *idxs;
25451f4df5f7SStefano Zampini     PetscScalar    *array;
25461f4df5f7SStefano Zampini     Vec            *work;
25471f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25484f1b2e48SStefano Zampini 
25494f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
25504f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
25511f4df5f7SStefano 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) */
25524edc6404Sstefano_zampini     if (checkb) {
25531f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
25541f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
25551f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25561f4df5f7SStefano Zampini       /* work[0] = 1_p */
25571f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
25581f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
25591f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25601f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
25611f4df5f7SStefano Zampini       /* work[0] = 1_v */
25621f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
25631f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
25641f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
25651f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
25661f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
25671f4df5f7SStefano Zampini     }
25684f1b2e48SStefano Zampini     if (nsubs > 1) {
25694f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
25704f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
25714f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
25724f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
25734f1b2e48SStefano Zampini         PetscInt               nl;
25744f1b2e48SStefano Zampini 
25754f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
25764f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
25774f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
25784f1b2e48SStefano Zampini         if (nl) {
25794f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
25804f1b2e48SStefano Zampini 
25814edc6404Sstefano_zampini           if (checkb) {
25821f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
25831f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
25841f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
25851f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
25861f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25871f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
25881f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
25891f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
25901f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
25911f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
25921f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
25931f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
25941f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
25951f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
25961f4df5f7SStefano Zampini                 break;
25971f4df5f7SStefano Zampini               }
25981f4df5f7SStefano Zampini             }
25991f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26001f4df5f7SStefano Zampini           }
26016632bad2Sstefano_zampini           if (valid && nneu) {
26026632bad2Sstefano_zampini             const PetscInt *idxs;
26031f4df5f7SStefano Zampini             PetscInt       nzb;
26041f4df5f7SStefano Zampini 
26056632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26066632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26076632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26081f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
26091f4df5f7SStefano Zampini           }
26101f4df5f7SStefano Zampini           if (valid && pressures) {
26114f1b2e48SStefano Zampini             IS t_pressure_subs;
26124f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26134f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
26144f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26154f1b2e48SStefano Zampini           }
26164f1b2e48SStefano Zampini           if (valid) {
26174f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
26184f1b2e48SStefano Zampini             pcbddc->benign_n++;
26194f1b2e48SStefano Zampini           } else {
26204f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
26214f1b2e48SStefano Zampini           }
26224f1b2e48SStefano Zampini         }
26234f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
26244f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
26254f1b2e48SStefano Zampini       }
26264f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
26274f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
26281f4df5f7SStefano Zampini 
26296632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
26301f4df5f7SStefano Zampini       if (valid && pressures) {
26314f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
26324f1b2e48SStefano Zampini       }
26334edc6404Sstefano_zampini       if (valid && checkb) {
26341f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
26351f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
26361f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26371f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
26381f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26391f4df5f7SStefano Zampini             valid = PETSC_FALSE;
26401f4df5f7SStefano Zampini             break;
26411f4df5f7SStefano Zampini           }
26421f4df5f7SStefano Zampini         }
26431f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26441f4df5f7SStefano Zampini       }
26454f1b2e48SStefano Zampini       if (valid) {
26464f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2647ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
26484f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26494f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
26504f1b2e48SStefano Zampini       }
26514f1b2e48SStefano Zampini     }
26524edc6404Sstefano_zampini     if (checkb) {
26531f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
26544f1b2e48SStefano Zampini     }
26551f4df5f7SStefano Zampini   }
26561f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
26574f1b2e48SStefano Zampini 
26584f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2659b9b0e38cSStefano Zampini     PetscInt n;
2660b9b0e38cSStefano Zampini 
26614f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26624f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2663b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2664b9b0e38cSStefano Zampini     if (n) {
26654f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
26664f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
26674f1b2e48SStefano Zampini     }
2668b9b0e38cSStefano Zampini   }
26694f1b2e48SStefano Zampini 
26704f1b2e48SStefano Zampini   /* final check for null pressures */
26714f1b2e48SStefano Zampini   if (zerodiag && pressures) {
26724f1b2e48SStefano Zampini     PetscInt nz,np;
26734f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26744f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
26754f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
26764f1b2e48SStefano Zampini   }
26774f1b2e48SStefano Zampini 
26784f1b2e48SStefano Zampini   if (recompute_zerodiag) {
26794f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26804f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
26814f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
26824f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
26834f1b2e48SStefano Zampini     } else {
26844f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
26854f1b2e48SStefano Zampini 
26864f1b2e48SStefano Zampini       nzn = 0;
26874f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26884f1b2e48SStefano Zampini         PetscInt ns;
26894f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
26904f1b2e48SStefano Zampini         nzn += ns;
26914f1b2e48SStefano Zampini       }
26924f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
26934f1b2e48SStefano Zampini       nzn = 0;
26944f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26954f1b2e48SStefano Zampini         PetscInt ns,*idxs;
26964f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
26974f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
26984f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
26994f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27004f1b2e48SStefano Zampini         nzn += ns;
27014f1b2e48SStefano Zampini       }
27024f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27034f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini     }
27054f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27064f1b2e48SStefano Zampini   }
27074f1b2e48SStefano Zampini 
2708669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2709a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2710a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2711a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2712a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2713a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2714a198735bSStefano Zampini 
27151f4df5f7SStefano Zampini     if (pressures) {
27161f4df5f7SStefano Zampini       isused = pressures;
27171f4df5f7SStefano Zampini     } else {
27184edc6404Sstefano_zampini       isused = zerodiag_save;
27191f4df5f7SStefano Zampini     }
2720a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2721669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
27221ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
27231ae86dd6SStefano 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");
2724a198735bSStefano Zampini     n_isused = 0;
2725a198735bSStefano Zampini     if (isused) {
2726a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2727a198735bSStefano Zampini     }
2728a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2729a198735bSStefano Zampini     st = st-n_isused;
27301ae86dd6SStefano Zampini     if (n) {
2731a198735bSStefano Zampini       const PetscInt *gidxs;
2732a198735bSStefano Zampini 
27337dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2734a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2735a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2736a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2737a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2738a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
27391ae86dd6SStefano Zampini     } else {
2740a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2741a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2742a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2743a198735bSStefano Zampini     }
2744a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2745a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2746a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2747a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2748a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2749a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2750a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2751a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2752a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2753a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2754a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2755a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2756a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2757a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
27581ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27591ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27601ae86dd6SStefano Zampini   }
27614edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2762b3afcdbeSStefano Zampini 
2763b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
27644f1b2e48SStefano Zampini   if (has_null_pressures) {
27654f1b2e48SStefano Zampini     IS             zerodiagc;
27664f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
27674f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
27684f1b2e48SStefano Zampini 
27694f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2770339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2771339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2772339f8db1SStefano Zampini     /* local change of basis for pressures */
2773339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
277497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2775339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2776339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2777339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
27784f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
27794f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
27804f1b2e48SStefano Zampini       PetscInt nzs,j;
27814f1b2e48SStefano Zampini 
27824f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
27834f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27844f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
27854f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
27864f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27874f1b2e48SStefano Zampini     }
2788339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2789339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2790339f8db1SStefano Zampini     /* set identity on velocities */
2791339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2792339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2793339f8db1SStefano Zampini     }
27944f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
27954f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
27969f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
27974f1b2e48SStefano 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);
2798339f8db1SStefano Zampini     /* set change on pressures */
27994f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28004f1b2e48SStefano Zampini       PetscScalar *array;
28014f1b2e48SStefano Zampini       PetscInt    nzs;
28024f1b2e48SStefano Zampini 
28034f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28044f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28054f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2806339f8db1SStefano Zampini         PetscScalar vals[2];
2807339f8db1SStefano Zampini         PetscInt    cols[2];
2808339f8db1SStefano Zampini 
2809339f8db1SStefano Zampini         cols[0] = idxs[i];
28104f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2811339f8db1SStefano Zampini         vals[0] = 1.;
2812b0f5fe93SStefano Zampini         vals[1] = 1.;
28134f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2814339f8db1SStefano Zampini       }
28154f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
28164f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
28174f1b2e48SStefano Zampini       array[nzs-1] = 1.;
28184f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
28194f1b2e48SStefano Zampini       /* store local idxs for p0 */
28204f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
28214f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2822339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
28234f1b2e48SStefano Zampini     }
2824339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2825339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2826a3df083aSStefano Zampini     /* project if needed */
2827a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28281dd7afcfSStefano Zampini       Mat M;
28291dd7afcfSStefano Zampini 
28301dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2831339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28321dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
28331dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2834a3df083aSStefano Zampini     }
28354f1b2e48SStefano Zampini     /* store global idxs for p0 */
28364f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2837339f8db1SStefano Zampini   }
2838ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28394f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2840b0f5fe93SStefano Zampini 
2841b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2842b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
284327b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
284427b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2845339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2846339f8db1SStefano Zampini   PetscFunctionReturn(0);
2847339f8db1SStefano Zampini }
2848339f8db1SStefano Zampini 
2849015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2850efc2fbd9SStefano Zampini {
2851efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2852de9d7bd0SStefano Zampini   PetscScalar    *array;
2853efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2854efc2fbd9SStefano Zampini 
2855efc2fbd9SStefano Zampini   PetscFunctionBegin;
2856efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2857efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
28584f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2859efc2fbd9SStefano Zampini   }
2860de9d7bd0SStefano Zampini   if (get) {
2861efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
28624f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
28634f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2864efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2865de9d7bd0SStefano Zampini   } else {
2866de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2867de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2868de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2869de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2870efc2fbd9SStefano Zampini   }
2871efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2872efc2fbd9SStefano Zampini }
2873efc2fbd9SStefano Zampini 
2874c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2875c263805aSStefano Zampini {
2876c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2877c263805aSStefano Zampini   PetscErrorCode ierr;
2878c263805aSStefano Zampini 
2879c263805aSStefano Zampini   PetscFunctionBegin;
2880c263805aSStefano Zampini   /* TODO: add error checking
2881c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2882c263805aSStefano Zampini     - cannot push before pop.
28831c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2884c263805aSStefano Zampini   */
28854f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2886efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2887efc2fbd9SStefano Zampini   }
2888c263805aSStefano Zampini   if (pop) {
2889a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28904f1b2e48SStefano Zampini       IS       is_p0;
28914f1b2e48SStefano Zampini       MatReuse reuse;
2892c263805aSStefano Zampini 
2893c263805aSStefano Zampini       /* extract B_0 */
28944f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
28954f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
28964f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
28974f1b2e48SStefano Zampini       }
28984f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
28997dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2900c263805aSStefano Zampini       /* remove rows and cols from local problem */
2901c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
290297d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29034f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29044f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2905a3df083aSStefano Zampini     } else {
2906a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2907a3df083aSStefano Zampini       PetscScalar *vals;
2908a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2909a3df083aSStefano Zampini 
2910a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2911a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2912a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
29130b5adadeSStefano Zampini         PetscInt *nnz;
2914a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2915a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2916a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2917331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2918331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2919331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2920331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2921331e053bSStefano Zampini         }
2922331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2923331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2924331e053bSStefano Zampini       }
2925a3df083aSStefano Zampini 
2926a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2927a3df083aSStefano Zampini         PetscScalar *array;
2928a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2929a3df083aSStefano Zampini 
2930a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2931a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2932a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2933a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2934a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2935a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2936a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2937a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2938a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2939a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2940a3df083aSStefano Zampini         cum = 0;
2941a3df083aSStefano Zampini         for (j=0;j<n;j++) {
294222db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2943a3df083aSStefano Zampini             vals[cum] = array[j];
2944a3df083aSStefano Zampini             idxs_ins[cum] = j;
2945a3df083aSStefano Zampini             cum++;
2946a3df083aSStefano Zampini           }
2947a3df083aSStefano Zampini         }
2948a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2949a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2950a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2951a3df083aSStefano Zampini       }
2952a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2953a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2954a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2955a3df083aSStefano Zampini     }
2956c263805aSStefano Zampini   } else { /* push */
2957a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29584f1b2e48SStefano Zampini       PetscInt i;
29594f1b2e48SStefano Zampini 
29604f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
29614f1b2e48SStefano Zampini         PetscScalar *B0_vals;
29624f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
29634f1b2e48SStefano Zampini 
29644f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29654f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29667b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29674f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
29684f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29694f1b2e48SStefano Zampini       }
2970c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2971c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2972a3df083aSStefano Zampini     } else {
2973a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2974a3df083aSStefano Zampini     }
2975c263805aSStefano Zampini   }
2976c263805aSStefano Zampini   PetscFunctionReturn(0);
2977c263805aSStefano Zampini }
2978c263805aSStefano Zampini 
297908122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2980b1b3d7a2SStefano Zampini {
2981b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
298208122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
298308122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
298408122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
298508122e43SStefano Zampini   PetscScalar     *work,lwork;
298608122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
298708122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
298808122e43SStefano Zampini   PetscReal       *eigs,thresh;
29891b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2990f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
299108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
299208122e43SStefano Zampini   PetscReal       *rwork;
299308122e43SStefano Zampini #endif
2994b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2995b1b3d7a2SStefano Zampini 
2996b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2997b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2998af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2999d750e150Sstefano_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);
300006a4e24aSStefano Zampini 
3001fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3002fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3003fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3004fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30051575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3006fd14bc51SStefano Zampini   }
3007fd14bc51SStefano Zampini 
3008e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
3009e496cd5dSStefano 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);
3010e496cd5dSStefano Zampini   }
3011e496cd5dSStefano Zampini 
301208122e43SStefano Zampini   /* max size of subsets */
301308122e43SStefano Zampini   mss = 0;
301408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
301508122e43SStefano Zampini     PetscInt subset_size;
3016862806e4SStefano Zampini 
301708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
301808122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
301908122e43SStefano Zampini   }
302008122e43SStefano Zampini 
302108122e43SStefano Zampini   /* min/max and threshold */
302208122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3023f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
302408122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3025f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3026f6f667cfSStefano Zampini   if (nmin) {
3027f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3028f6f667cfSStefano Zampini   }
302908122e43SStefano Zampini 
303008122e43SStefano Zampini   /* allocate lapack workspace */
303108122e43SStefano Zampini   cum = cum2 = 0;
303208122e43SStefano Zampini   maxneigs = 0;
303308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
303408122e43SStefano Zampini     PetscInt n,subset_size;
3035f6f667cfSStefano Zampini 
303608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
303708122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
30389162d606SStefano Zampini     cum += subset_size;
30399162d606SStefano Zampini     cum2 += subset_size*n;
304008122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
304108122e43SStefano Zampini   }
304208122e43SStefano Zampini   if (mss) {
30439ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
304408122e43SStefano Zampini       PetscBLASInt B_itype = 1;
304508122e43SStefano Zampini       PetscBLASInt B_N = mss;
30464c6709b3SStefano Zampini       PetscReal    zero = 0.0;
30474c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
304808122e43SStefano Zampini 
304908122e43SStefano Zampini       B_lwork = -1;
305008122e43SStefano Zampini       S = NULL;
305108122e43SStefano Zampini       St = NULL;
3052a58a30b4SStefano Zampini       eigs = NULL;
3053a58a30b4SStefano Zampini       eigv = NULL;
3054a58a30b4SStefano Zampini       B_iwork = NULL;
3055a58a30b4SStefano Zampini       B_ifail = NULL;
3056d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3057d1710679SStefano Zampini       rwork = NULL;
3058d1710679SStefano Zampini #endif
30598bec7fa6SStefano Zampini       thresh = 1.0;
306008122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
306108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
306208122e43SStefano 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));
306308122e43SStefano Zampini #else
306408122e43SStefano 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));
306508122e43SStefano Zampini #endif
306608122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
306708122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
306808122e43SStefano Zampini     } else {
306908122e43SStefano Zampini         /* TODO */
307008122e43SStefano Zampini     }
307108122e43SStefano Zampini   } else {
307208122e43SStefano Zampini     lwork = 0;
307308122e43SStefano Zampini   }
307408122e43SStefano Zampini 
307508122e43SStefano Zampini   nv = 0;
3076d62866d3SStefano 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) */
3077d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
307808122e43SStefano Zampini   }
30794c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3080f6f667cfSStefano Zampini   if (allocated_S_St) {
3081f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3082f6f667cfSStefano Zampini   }
3083f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
308408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
308508122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
308608122e43SStefano Zampini #endif
30879162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
30889162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
30899162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
309008122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
30919162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
309208122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
309308122e43SStefano Zampini 
309408122e43SStefano Zampini   maxneigs = 0;
309572b8c272SStefano Zampini   cum = cumarray = 0;
30969162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
30979162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3098d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
309908122e43SStefano Zampini     const PetscInt *idxs;
310008122e43SStefano Zampini 
3101d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
310208122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
310308122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
310408122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
310508122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31069162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31079162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
310808122e43SStefano Zampini     }
3109d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
311008122e43SStefano Zampini   }
311108122e43SStefano Zampini 
311208122e43SStefano Zampini   if (mss) { /* multilevel */
311308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
311408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
311508122e43SStefano Zampini   }
311608122e43SStefano Zampini 
3117ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
311808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
311908122e43SStefano Zampini     const PetscInt *idxs;
31209d54b7f4SStefano Zampini     PetscReal      upper,lower;
3121862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
312208122e43SStefano Zampini     PetscBLASInt   B_N;
3123aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
312408122e43SStefano Zampini 
31259d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
31269d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
31279d54b7f4SStefano Zampini       lower = thresh;
31289d54b7f4SStefano Zampini     } else {
31299d54b7f4SStefano Zampini       upper = 1./thresh;
31309d54b7f4SStefano Zampini       lower = 0.;
31319d54b7f4SStefano Zampini     }
3132862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3133ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3134f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3135f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
31369ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
3137aff50787SStefano Zampini         PetscInt j,k;
3138aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3139aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3140aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
314108122e43SStefano Zampini         }
314208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3143aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3144aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3145aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3146aff50787SStefano Zampini           }
314708122e43SStefano Zampini         }
314808122e43SStefano Zampini       } else {
314908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
315008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
315108122e43SStefano Zampini       }
31528bec7fa6SStefano Zampini     } else {
3153f6f667cfSStefano Zampini       S = Sarray + cumarray;
3154f6f667cfSStefano Zampini       St = Starray + cumarray;
31558bec7fa6SStefano Zampini     }
3156aff50787SStefano Zampini     /* see if we can save some work */
3157b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3158aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3159aff50787SStefano Zampini     }
3160aff50787SStefano Zampini 
3161b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3162aff50787SStefano Zampini       B_neigs = 0;
3163aff50787SStefano Zampini     } else {
31649ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
316508122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3166f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
31674c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
31689552c7c7SStefano Zampini         PetscInt     nmin_s;
3169b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
317008122e43SStefano Zampini 
3171fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3172eee23b56SStefano 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]]);
3173fd14bc51SStefano Zampini         }
3174d16cbb6bSStefano Zampini 
3175b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
3176b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
3177b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
3178b7ab4a40SStefano Zampini         }
3179b7ab4a40SStefano Zampini 
318008122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3181b7ab4a40SStefano Zampini         if (compute_range) {
3182d16cbb6bSStefano Zampini 
3183d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
318408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
31859d54b7f4SStefano 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));
318608122e43SStefano Zampini #else
31879d54b7f4SStefano 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));
318808122e43SStefano Zampini #endif
3189b7ab4a40SStefano Zampini         } else if (!same_data) {
3190d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3191d16cbb6bSStefano Zampini           B_IL = 1;
3192d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
31939d54b7f4SStefano 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));
3194d16cbb6bSStefano Zampini #else
31959d54b7f4SStefano 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));
3196d16cbb6bSStefano Zampini #endif
3197b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3198b7ab4a40SStefano Zampini           PetscInt k;
3199b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3200b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3201b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3202b7ab4a40SStefano Zampini           nmin = nmax;
3203b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3204b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3205b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3206b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3207b7ab4a40SStefano Zampini           }
3208d16cbb6bSStefano Zampini         }
320908122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
321008122e43SStefano Zampini         if (B_ierr) {
32116c4ed002SBarry 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);
32126c4ed002SBarry 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);
32136c4ed002SBarry 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);
321408122e43SStefano Zampini         }
321508122e43SStefano Zampini 
321608122e43SStefano Zampini         if (B_neigs > nmax) {
3217fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3218fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
3219fd14bc51SStefano Zampini           }
32209d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
322108122e43SStefano Zampini           B_neigs = nmax;
322208122e43SStefano Zampini         }
322308122e43SStefano Zampini 
32249552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
32259552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
322608122e43SStefano Zampini           PetscBLASInt B_neigs2;
322708122e43SStefano Zampini 
32289d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3229f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
32309d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
32319d54b7f4SStefano Zampini           } else {
32329d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
32339d54b7f4SStefano Zampini             B_IU = nmin_s;
32349d54b7f4SStefano Zampini           }
3235fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3236fd14bc51SStefano 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);
3237fd14bc51SStefano Zampini           }
32389ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
32391ae86dd6SStefano Zampini             PetscInt j,k;
324008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
32411ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
32421ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
32431ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
324408122e43SStefano Zampini               }
324508122e43SStefano Zampini             }
324608122e43SStefano Zampini           } else {
324708122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
324808122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
324908122e43SStefano Zampini           }
325008122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
325108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32529d54b7f4SStefano 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));
325308122e43SStefano Zampini #else
32549d54b7f4SStefano 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));
325508122e43SStefano Zampini #endif
325608122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
325708122e43SStefano Zampini           B_neigs += B_neigs2;
325808122e43SStefano Zampini         }
325908122e43SStefano Zampini         if (B_ierr) {
32606c4ed002SBarry 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);
32616c4ed002SBarry 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);
32626c4ed002SBarry 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);
326308122e43SStefano Zampini         }
3264fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3265ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
326608122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
326708122e43SStefano Zampini             if (eigs[j] == 0.0) {
3268ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
326908122e43SStefano Zampini             } else {
32709d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3271ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
32729d54b7f4SStefano Zampini               } else {
32739d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
32749d54b7f4SStefano Zampini               }
3275fd14bc51SStefano Zampini             }
327608122e43SStefano Zampini           }
327708122e43SStefano Zampini         }
327808122e43SStefano Zampini       } else {
327908122e43SStefano Zampini           /* TODO */
328008122e43SStefano Zampini       }
3281aff50787SStefano Zampini     }
32826c3e6151SStefano Zampini     /* change the basis back to the original one */
32836c3e6151SStefano Zampini     if (sub_schurs->change) {
328472b8c272SStefano Zampini       Mat change,phi,phit;
32856c3e6151SStefano Zampini 
328603dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
32876c3e6151SStefano Zampini         PetscInt ii;
32886c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
32896c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
32906c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3291684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3292684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3293684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3294684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3295684229deSStefano Zampini #else
32966c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3297684229deSStefano Zampini #endif
32986c3e6151SStefano Zampini           }
32996c3e6151SStefano Zampini         }
33006c3e6151SStefano Zampini       }
330172b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
33026c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
330372b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
33046c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
33056c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
33066c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
33076c3e6151SStefano Zampini     }
33088bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
33098bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
33109162d606SStefano Zampini     if (B_neigs) {
33119162d606SStefano 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);
3312fd14bc51SStefano Zampini 
3313fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
33149552c7c7SStefano Zampini         PetscInt ii;
33159552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3316ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
33179552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3318ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3319ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3320ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3321ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3322ac47001eSStefano Zampini #else
3323ac47001eSStefano 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);
3324ac47001eSStefano Zampini #endif
33259552c7c7SStefano Zampini           }
33269552c7c7SStefano Zampini         }
3327fd14bc51SStefano Zampini       }
33289162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
33299162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
33309162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
33319162d606SStefano Zampini       cum++;
333208122e43SStefano Zampini     }
333308122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
333408122e43SStefano Zampini     /* shift for next computation */
333508122e43SStefano Zampini     cumarray += subset_size*subset_size;
333608122e43SStefano Zampini   }
3337fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3338fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3339fd14bc51SStefano Zampini   }
334008122e43SStefano Zampini 
334108122e43SStefano Zampini   if (mss) {
334208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
334308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3344f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3345f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3346f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
334708122e43SStefano Zampini   }
3348f6f667cfSStefano Zampini   if (allocated_S_St) {
3349f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3350f6f667cfSStefano Zampini   }
3351f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
335208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
335308122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
335408122e43SStefano Zampini #endif
335508122e43SStefano Zampini   if (pcbddc->dbg_flag) {
33561b968477SStefano Zampini     PetscInt maxneigs_r;
3357b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
33589b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
335908122e43SStefano Zampini   }
336008122e43SStefano Zampini   PetscFunctionReturn(0);
336108122e43SStefano Zampini }
3362b1b3d7a2SStefano Zampini 
3363c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3364c8587f34SStefano Zampini {
33658629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3366c8587f34SStefano Zampini   PetscErrorCode ierr;
3367c8587f34SStefano Zampini 
3368c8587f34SStefano Zampini   PetscFunctionBegin;
3369f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
33705e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3371c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3372c8587f34SStefano Zampini 
3373684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
33740fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3375684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3376c8587f34SStefano Zampini 
33778629588bSStefano Zampini   /*
33788629588bSStefano Zampini      Setup local correction and local part of coarse basis.
33798629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
33808629588bSStefano Zampini   */
338147f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
33828629588bSStefano Zampini 
33838629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
33848629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
33858629588bSStefano Zampini 
33868629588bSStefano Zampini   /* free */
33878629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3388c8587f34SStefano Zampini   PetscFunctionReturn(0);
3389c8587f34SStefano Zampini }
3390c8587f34SStefano Zampini 
3391674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3392674ae819SStefano Zampini {
3393674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3394674ae819SStefano Zampini   PetscErrorCode ierr;
3395674ae819SStefano Zampini 
3396674ae819SStefano Zampini   PetscFunctionBegin;
3397674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
339830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3399674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3400785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3401674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3402f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3403f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3404785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
340563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
340663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3407674ae819SStefano Zampini   PetscFunctionReturn(0);
3408674ae819SStefano Zampini }
3409674ae819SStefano Zampini 
3410674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3411674ae819SStefano Zampini {
3412674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
34134f1b2e48SStefano Zampini   PetscInt       i;
3414674ae819SStefano Zampini   PetscErrorCode ierr;
3415674ae819SStefano Zampini 
3416674ae819SStefano Zampini   PetscFunctionBegin;
34171e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
34181e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3419a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3420b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3421674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
342216909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
34231dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3424674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3425669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3426fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
34279326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
34284f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
34294f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
34304f1b2e48SStefano Zampini   }
3431e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
34324f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3433e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3434c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
34358af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3436674ae819SStefano Zampini   PetscFunctionReturn(0);
3437674ae819SStefano Zampini }
3438674ae819SStefano Zampini 
3439674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3440674ae819SStefano Zampini {
3441674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3442674ae819SStefano Zampini   PetscErrorCode ierr;
3443674ae819SStefano Zampini 
3444674ae819SStefano Zampini   PetscFunctionBegin;
3445674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
344658da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3447ca92afb2SStefano Zampini     PetscScalar *array;
344806656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
344906656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
345058da7f69SStefano Zampini   }
3451674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3452674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
345315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
345415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3455674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3456674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3457674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
345806656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3459674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3460674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
34618ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3462674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3463674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3464674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
34659326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
34669326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
34679326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3468f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3469727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
34700e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3471f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
347270cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
347381d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
34740369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
34751dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
34764f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
34778b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3478ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3479ca92afb2SStefano Zampini     PetscInt i;
3480ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3481ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3482ca92afb2SStefano Zampini     }
3483ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3484ca92afb2SStefano Zampini   }
34854f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3486674ae819SStefano Zampini   PetscFunctionReturn(0);
3487674ae819SStefano Zampini }
3488674ae819SStefano Zampini 
3489f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
34906bfb1811SStefano Zampini {
34916bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
34926bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
34936bfb1811SStefano Zampini   VecType        impVecType;
34944f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
34956bfb1811SStefano Zampini   PetscErrorCode ierr;
34966bfb1811SStefano Zampini 
34976bfb1811SStefano Zampini   PetscFunctionBegin;
34984f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3499b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
35006bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3501e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3502e7b262bdSStefano Zampini   /* R nodes */
3503e7b262bdSStefano Zampini   old_size = -1;
3504e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3505e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3506e7b262bdSStefano Zampini   }
3507e7b262bdSStefano Zampini   if (n_R != old_size) {
3508e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3509e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
35106bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
35116bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
35126bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
35136bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3514e7b262bdSStefano Zampini   }
3515e7b262bdSStefano Zampini   /* local primal dofs */
3516e7b262bdSStefano Zampini   old_size = -1;
3517e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3518e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3519e7b262bdSStefano Zampini   }
3520e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3521e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
352283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3523e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
35246bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3525e7b262bdSStefano Zampini   }
3526e7b262bdSStefano Zampini   /* local explicit constraints */
3527e7b262bdSStefano Zampini   old_size = -1;
3528e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3529e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3530e7b262bdSStefano Zampini   }
3531e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3532e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
353383b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
353483b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
353583b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
353683b7ccabSStefano Zampini   }
35376bfb1811SStefano Zampini   PetscFunctionReturn(0);
35386bfb1811SStefano Zampini }
35396bfb1811SStefano Zampini 
354047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
354188ebb749SStefano Zampini {
354225084f0cSStefano Zampini   PetscErrorCode  ierr;
354325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
354488ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
354588ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3546d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
354725084f0cSStefano Zampini   /* submatrices of local problem */
354880677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
354906656605SStefano Zampini   /* submatrices of local coarse problem */
355006656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
355125084f0cSStefano Zampini   /* working matrices */
355206656605SStefano Zampini   Mat             C_CR;
355325084f0cSStefano Zampini   /* additional working stuff */
355406656605SStefano Zampini   PC              pc_R;
3555c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
35565cbda25cSStefano Zampini   Vec             dummy_vec;
3557c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
355825084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
355906656605SStefano Zampini   PetscScalar     *work;
356006656605SStefano Zampini   PetscInt        *idx_V_B;
3561ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
356206656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3563ffd830a3SStefano Zampini 
356425084f0cSStefano Zampini   /* some shortcuts to scalars */
356506656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
356688ebb749SStefano Zampini 
356788ebb749SStefano Zampini   PetscFunctionBegin;
35689a962809SStefano 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");
3569ffd830a3SStefano Zampini 
3570ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3571b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
35724f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3573b371cd4fSStefano Zampini   n_B = pcis->n_B;
3574b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
357588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
357688ebb749SStefano Zampini 
357788ebb749SStefano Zampini   /* vertices in boundary numbering */
3578785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
35790e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
35806c4ed002SBarry 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);
358188ebb749SStefano Zampini 
358206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3583019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
358406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
358506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
358606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
358706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
358806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
358906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
359006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
359106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
359206656605SStefano Zampini 
359306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
359406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
359506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
359606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
359706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3598ffd830a3SStefano Zampini   lda_rhs = n_R;
3599a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
360006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
360106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3602b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3603df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3604d62866d3SStefano Zampini     MatFactorType      type;
3605d62866d3SStefano Zampini 
3606df4d28bfSStefano Zampini     F = reuse_solver->F;
36076816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3608d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3609ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
361022db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
361106656605SStefano Zampini   } else {
361206656605SStefano Zampini     F = NULL;
361306656605SStefano Zampini   }
361406656605SStefano Zampini 
3615c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3616c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3617c58f9fdbSStefano Zampini   if (F) {
3618ea799195SBarry Smith     MatSolverType solver;
3619c58f9fdbSStefano Zampini 
36203ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3621c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3622c58f9fdbSStefano Zampini   }
3623c58f9fdbSStefano Zampini 
3624ffd830a3SStefano Zampini   /* allocate workspace */
3625ffd830a3SStefano Zampini   n = 0;
3626ffd830a3SStefano Zampini   if (n_constraints) {
3627ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3628ffd830a3SStefano Zampini   }
3629ffd830a3SStefano Zampini   if (n_vertices) {
3630ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3631ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3632ffd830a3SStefano Zampini   }
36332a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
36342a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
36352a3a6641Sstefano_zampini   }
3636ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3637ffd830a3SStefano Zampini 
36385cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
36395cbda25cSStefano Zampini   dummy_vec = NULL;
36405cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
36415cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
36425cbda25cSStefano Zampini   }
36435cbda25cSStefano Zampini 
364488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
364588ebb749SStefano Zampini   if (n_constraints) {
3646837cedc9SStefano Zampini     Mat         M3,C_B;
364706656605SStefano Zampini     IS          is_aux;
364880677318SStefano Zampini     PetscScalar *array,*array2;
364906656605SStefano Zampini 
3650f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
365180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
365288ebb749SStefano Zampini 
365325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
365425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
36557dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
36567dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
365788ebb749SStefano Zampini 
365880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
365980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3660c58f9fdbSStefano Zampini     if (!sparserhs) {
3661ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
366288ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
366306656605SStefano Zampini         const PetscScalar *row_cmat_values;
366406656605SStefano Zampini         const PetscInt    *row_cmat_indices;
366506656605SStefano Zampini         PetscInt          size_of_constraint,j;
366688ebb749SStefano Zampini 
366706656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
366806656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3669ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
367006656605SStefano Zampini         }
367106656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
367206656605SStefano Zampini       }
3673c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3674c58f9fdbSStefano Zampini     } else {
3675c58f9fdbSStefano Zampini       Mat tC_CR;
3676c58f9fdbSStefano Zampini 
3677c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3678c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3679c58f9fdbSStefano Zampini         PetscScalar *aa;
3680c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3681c58f9fdbSStefano Zampini         PetscBool   done;
3682c58f9fdbSStefano Zampini 
3683c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
368413903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3685c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3686c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3687c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
368813903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3689c58f9fdbSStefano Zampini       } else {
3690c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3691c58f9fdbSStefano Zampini         tC_CR = C_CR;
3692c58f9fdbSStefano Zampini       }
3693c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3694c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3695c58f9fdbSStefano Zampini     }
3696ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
369706656605SStefano Zampini     if (F) {
3698a3df083aSStefano Zampini       if (need_benign_correction) {
3699df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3700a3df083aSStefano Zampini 
370172b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
370272b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3703a3df083aSStefano Zampini       }
3704c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3705a3df083aSStefano Zampini       if (need_benign_correction) {
3706a3df083aSStefano Zampini         PetscScalar        *marr;
3707df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3708a3df083aSStefano Zampini 
3709a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
37105cbda25cSStefano Zampini         if (lda_rhs != n_R) {
37115cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
37125cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
37135cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
37145cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
37155cbda25cSStefano Zampini           }
37165cbda25cSStefano Zampini         } else {
3717a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3718a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
37195cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3720a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3721a3df083aSStefano Zampini           }
37225cbda25cSStefano Zampini         }
3723a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3724a3df083aSStefano Zampini       }
372506656605SStefano Zampini     } else {
372680677318SStefano Zampini       PetscScalar *marr;
372780677318SStefano Zampini 
372880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
372906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3730ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3731ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
373206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
373306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
373406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
373506656605SStefano Zampini       }
373680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
373706656605SStefano Zampini     }
3738c58f9fdbSStefano Zampini     if (sparserhs) {
3739c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3740c58f9fdbSStefano Zampini     }
3741c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
374280677318SStefano Zampini     if (!pcbddc->switch_static) {
374380677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
374480677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
374580677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
374680677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3747ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
374880677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
374980677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
375080677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
375180677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
375280677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
375380677318SStefano Zampini       }
375480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
375580677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
375672b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
375780677318SStefano Zampini     } else {
3758ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3759ffd830a3SStefano Zampini         IS dummy;
3760ffd830a3SStefano Zampini 
3761ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
37627dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3763ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3764ffd830a3SStefano Zampini       } else {
376580677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
376680677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3767ffd830a3SStefano Zampini       }
376825084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
376980677318SStefano Zampini     }
377080677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
377180677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
377280677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
377380677318SStefano Zampini     if (isCHOL) {
377480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
377580677318SStefano Zampini     } else {
377625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
377780677318SStefano Zampini     }
3778837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
377980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
3780837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
378172b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
3782837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
3783837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
3784f4ddd8eeSStefano Zampini   }
3785fc227af8SStefano Zampini 
3786fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
378788ebb749SStefano Zampini   if (n_vertices) {
378806656605SStefano Zampini     IS        is_aux;
3789c58f9fdbSStefano Zampini     PetscBool isseqaij;
37903a50541eSStefano Zampini 
3791b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
37926816873aSStefano Zampini       IS tis;
37936816873aSStefano Zampini 
37946816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
37956816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
37966816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
37976816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
37986816873aSStefano Zampini     } else {
37993a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
38006816873aSStefano Zampini     }
38017dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
38027dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3803c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3804c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
3805c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3806c58f9fdbSStefano Zampini     }
38077dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
380825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
380988ebb749SStefano Zampini   }
381088ebb749SStefano Zampini 
381188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3812f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
381306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
381406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
381506656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
381606656605SStefano Zampini     }
3817f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
381806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
381906656605SStefano Zampini       PetscScalar *marray;
382006656605SStefano Zampini 
382106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
382206656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3823f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3824f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3825f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3826f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3827f4ddd8eeSStefano Zampini     }
3828f4ddd8eeSStefano Zampini   }
382906656605SStefano Zampini 
3830f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
3831a6e023c1Sstefano_zampini     PetscScalar *marr;
383288ebb749SStefano Zampini 
3833a6e023c1Sstefano_zampini     /* memory size */
383406656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
3835a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
3836a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
3837a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
3838a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3839a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
38408eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3841a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3842a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
384388ebb749SStefano Zampini     }
38443301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
3845a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3846a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
38478eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3848a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
384988ebb749SStefano Zampini       }
385088ebb749SStefano Zampini     } else {
3851c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3852c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
38531b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3854c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3855c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3856c0553b1fSStefano Zampini       }
385788ebb749SStefano Zampini     }
385806656605SStefano Zampini   }
3859019a44ceSStefano Zampini 
386006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
38614f1b2e48SStefano Zampini   p0_lidx_I = NULL;
38624f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3863d12edf2fSStefano Zampini     const PetscInt *idxs;
3864d12edf2fSStefano Zampini 
3865d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
38664f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
38674f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
38684f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
38694f1b2e48SStefano Zampini     }
3870d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3871d12edf2fSStefano Zampini   }
3872d16cbb6bSStefano Zampini 
387306656605SStefano Zampini   /* vertices */
387406656605SStefano Zampini   if (n_vertices) {
3875c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
387616f15bc4SStefano Zampini 
3877af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
387804708bb6SStefano Zampini 
387916f15bc4SStefano Zampini     if (n_R) {
388014393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
388106656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
388216f15bc4SStefano Zampini       PetscScalar  *x,*y;
388306656605SStefano Zampini 
388421eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
388514393ed6SStefano Zampini       if (need_benign_correction) {
388614393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
388714393ed6SStefano Zampini         IS                     is_p0;
388814393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
388914393ed6SStefano Zampini 
389014393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
389114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
389214393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3893af25d912SStefano 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);
389414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
389514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
38967dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
389714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
389814393ed6SStefano Zampini       }
389914393ed6SStefano Zampini 
3900c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3901c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
3902ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
3903af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3904ffd830a3SStefano Zampini         } else {
3905ca92afb2SStefano Zampini           PetscScalar    *av,*array;
3906ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
3907ca92afb2SStefano Zampini           PetscInt       n;
3908ca92afb2SStefano Zampini           PetscBool      flg_row;
3909ffd830a3SStefano Zampini 
3910ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
3911ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
39129d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3913ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3914ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3915ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
3916ca92afb2SStefano Zampini             PetscInt j;
3917ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3918ffd830a3SStefano Zampini           }
3919ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3920ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3921ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3922ffd830a3SStefano Zampini         }
3923a3df083aSStefano Zampini         if (need_benign_correction) {
3924df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3925a3df083aSStefano Zampini           PetscScalar        *marr;
3926a3df083aSStefano Zampini 
3927a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
392814393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
392914393ed6SStefano Zampini 
393014393ed6SStefano Zampini                  | 0 0  0 | (V)
393114393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
393214393ed6SStefano Zampini                  | 0 0 -1 | (p0)
393314393ed6SStefano Zampini 
393414393ed6SStefano Zampini           */
3935df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
393614393ed6SStefano Zampini             const PetscScalar *vals;
393714393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
393814393ed6SStefano Zampini             PetscInt          n,j,nz;
393914393ed6SStefano Zampini 
3940df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3941df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
394214393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
394314393ed6SStefano Zampini             for (j=0;j<n;j++) {
394414393ed6SStefano Zampini               PetscScalar val = vals[j];
394514393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
394614393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
394714393ed6SStefano Zampini             }
394814393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3949df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
395014393ed6SStefano Zampini           }
395172b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
395272b8c272SStefano Zampini         }
3953c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
3954c58f9fdbSStefano Zampini         Brhs = A_RV;
3955c58f9fdbSStefano Zampini       } else {
3956c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
3957c58f9fdbSStefano Zampini 
3958c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
3959fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
3960c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
3961c58f9fdbSStefano Zampini         } else {
3962c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
3963c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
3964c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
3965c58f9fdbSStefano Zampini           A_RVT = A_VR;
3966c58f9fdbSStefano Zampini         }
3967c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
3968c58f9fdbSStefano Zampini           PetscScalar *aa;
3969c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
3970c58f9fdbSStefano Zampini           PetscBool   done;
3971c58f9fdbSStefano Zampini 
3972c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
397313903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3974c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
3975c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
3976c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
397713903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3978c58f9fdbSStefano Zampini         } else {
3979c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
3980c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
3981c58f9fdbSStefano Zampini         }
3982c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
3983c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
3984c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
3985c58f9fdbSStefano Zampini       }
398672b8c272SStefano Zampini       if (F) {
398714393ed6SStefano Zampini         /* need to correct the rhs */
398872b8c272SStefano Zampini         if (need_benign_correction) {
398972b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
399072b8c272SStefano Zampini           PetscScalar        *marr;
399172b8c272SStefano Zampini 
3992c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
39935cbda25cSStefano Zampini           if (lda_rhs != n_R) {
39945cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
39955cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
39965cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
39975cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
39985cbda25cSStefano Zampini             }
39995cbda25cSStefano Zampini           } else {
4000a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4001a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4003a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4004a3df083aSStefano Zampini             }
40055cbda25cSStefano Zampini           }
4006c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4007a3df083aSStefano Zampini         }
4008c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4009c58f9fdbSStefano Zampini         if (restoreavr) {
4010c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4011c58f9fdbSStefano Zampini         }
401214393ed6SStefano Zampini         /* need to correct the solution */
4013a3df083aSStefano Zampini         if (need_benign_correction) {
4014df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4015a3df083aSStefano Zampini           PetscScalar        *marr;
4016a3df083aSStefano Zampini 
4017a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
40185cbda25cSStefano Zampini           if (lda_rhs != n_R) {
40195cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
40205cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40215cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40225cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40235cbda25cSStefano Zampini             }
40245cbda25cSStefano Zampini           } else {
4025a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4026a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40275cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4028a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4029a3df083aSStefano Zampini             }
40305cbda25cSStefano Zampini           }
4031a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4032a3df083aSStefano Zampini         }
403306656605SStefano Zampini       } else {
4034c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
403506656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4036ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4037ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
403806656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
403906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
404006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
404106656605SStefano Zampini         }
4042c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
404306656605SStefano Zampini       }
404480677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4045c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4046ffd830a3SStefano Zampini       /* S_VV and S_CV */
404706656605SStefano Zampini       if (n_constraints) {
404806656605SStefano Zampini         Mat B;
404980677318SStefano Zampini 
4050ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
405180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4052ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4053ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
405480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
405580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
405680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
405780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
405880677318SStefano Zampini         }
4059ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
406080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
406180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4062ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
406380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
406406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4065ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4066ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
406706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
406806656605SStefano Zampini       }
4069ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4070ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4071ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4072ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4073ffd830a3SStefano Zampini       }
407406656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
407514393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
407614393ed6SStefano Zampini       if (need_benign_correction) {
4077df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
407814393ed6SStefano Zampini         PetscScalar      *marr,*sums;
407914393ed6SStefano Zampini 
408014393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4081f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4082df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
408314393ed6SStefano Zampini           const PetscScalar *vals;
408414393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
408514393ed6SStefano Zampini           PetscInt          n,j,nz;
408614393ed6SStefano Zampini 
4087df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4088df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
408914393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
409014393ed6SStefano Zampini             PetscInt k;
409114393ed6SStefano Zampini             sums[j] = 0.;
409214393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
409314393ed6SStefano Zampini           }
409414393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
409514393ed6SStefano Zampini           for (j=0;j<n;j++) {
409614393ed6SStefano Zampini             PetscScalar val = vals[j];
409714393ed6SStefano Zampini             PetscInt k;
409814393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
409914393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
410014393ed6SStefano Zampini             }
410114393ed6SStefano Zampini           }
410214393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4103df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
410414393ed6SStefano Zampini         }
410514393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4106f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
410714393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
410814393ed6SStefano Zampini       }
410980677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
411006656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
411106656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
411206656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
411306656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
411406656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
411506656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
411606656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4117d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4118019a44ceSStefano Zampini     } else {
4119d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4120d16cbb6bSStefano Zampini     }
412121eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4122d16cbb6bSStefano Zampini 
412306656605SStefano Zampini     /* coarse basis functions */
412406656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
412516f15bc4SStefano Zampini       PetscScalar *y;
412616f15bc4SStefano Zampini 
4127ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
412806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
412906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
413006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
413106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
413206656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
413306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
413406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
413506656605SStefano Zampini 
413606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41374f1b2e48SStefano Zampini         PetscInt j;
41384f1b2e48SStefano Zampini 
413906656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
414006656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
414106656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
414206656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
414306656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
41444f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
414506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
414606656605SStefano Zampini       }
414706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
414806656605SStefano Zampini     }
414904708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
415004708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
415106656605SStefano Zampini   }
41525cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
415306656605SStefano Zampini 
415406656605SStefano Zampini   if (n_constraints) {
415506656605SStefano Zampini     Mat B;
415606656605SStefano Zampini 
4157ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
415806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
415980677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
416006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
416106656605SStefano Zampini     if (n_vertices) {
416203dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
416380677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
416480677318SStefano Zampini       } else {
416580677318SStefano Zampini         Mat S_VCt;
416680677318SStefano Zampini 
4167ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4168ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
416972b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4170ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4171ffd830a3SStefano Zampini         }
417280677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
417380677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
417480677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
417580677318SStefano Zampini       }
417606656605SStefano Zampini     }
417706656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
417806656605SStefano Zampini     /* coarse basis functions */
417906656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
418006656605SStefano Zampini       PetscScalar *y;
418106656605SStefano Zampini 
4182ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
418306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
418406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
418506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
418606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
418706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
418806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
418906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41904f1b2e48SStefano Zampini         PetscInt j;
41914f1b2e48SStefano Zampini 
419206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
419306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
419406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
419506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
419606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
41974f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
419806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
419906656605SStefano Zampini       }
420006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
420106656605SStefano Zampini     }
420206656605SStefano Zampini   }
420380677318SStefano Zampini   if (n_constraints) {
420480677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
420580677318SStefano Zampini   }
42064f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
420772b8c272SStefano Zampini 
420872b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
420972b8c272SStefano Zampini   if (pcbddc->benign_n) {
421072b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
421172b8c272SStefano Zampini     IS          is_dummy;
421272b8c272SStefano Zampini     PetscScalar *data;
421372b8c272SStefano Zampini     PetscInt    j;
421472b8c272SStefano Zampini 
421572b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
42167dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
421772b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
421872b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
421986c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
422072b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
422172b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
422272b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
422372b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
422472b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
422572b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
422672b8c272SStefano Zampini       }
422772b8c272SStefano Zampini     }
422872b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
422972b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
423072b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
423172b8c272SStefano Zampini   }
4232019a44ceSStefano Zampini 
423306656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
42343301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4235ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4236ffd830a3SStefano Zampini     PetscScalar *marray;
423706656605SStefano Zampini 
423806656605SStefano Zampini     if (n_constraints) {
4239ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
424006656605SStefano Zampini 
4241abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
424206656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4243ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
424416f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
424506656605SStefano Zampini       if (n_vertices) {
4246ffd830a3SStefano Zampini         Mat S_VCT;
424706656605SStefano Zampini 
424806656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4249ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
425016f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
425106656605SStefano Zampini       }
4252ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
42535b782168SStefano Zampini     } else {
42545b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
425506656605SStefano Zampini     }
425616f15bc4SStefano Zampini     if (n_vertices && n_R) {
4257ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4258ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4259ffd830a3SStefano Zampini       PetscInt       n;
4260ffd830a3SStefano Zampini       PetscBool      flg_row;
426106656605SStefano Zampini 
4262ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4263af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4264ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4265ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4266ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4267ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4268ffd830a3SStefano Zampini         PetscInt j;
4269ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4270ffd830a3SStefano Zampini       }
4271ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4272ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4273ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
427406656605SStefano Zampini     }
427506656605SStefano Zampini 
4276ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4277abc8f43dSstefano_zampini     if (n_vertices) {
4278ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4279ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4280ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4281ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
428206656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
428306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
428406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
428506656605SStefano Zampini       }
4286ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4287abc8f43dSstefano_zampini     }
42885b782168SStefano Zampini     if (B_C) {
4289ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4290ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4291ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4292ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4293ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4294ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4295ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
429606656605SStefano Zampini       }
4297ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
42985b782168SStefano Zampini     }
429906656605SStefano Zampini     /* coarse basis functions */
430006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
430106656605SStefano Zampini       PetscScalar *y;
430206656605SStefano Zampini 
4303ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
430406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
430506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
430606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
430706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
430806656605SStefano Zampini       if (i<n_vertices) {
430906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
431006656605SStefano Zampini       }
431106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
431206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
431306656605SStefano Zampini 
431406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
431506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
431606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
431706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
431806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
431906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
432006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
432106656605SStefano Zampini       }
432206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
432306656605SStefano Zampini     }
4324ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4325ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
432606656605SStefano Zampini   }
4327a6e023c1Sstefano_zampini 
4328d62866d3SStefano Zampini   /* free memory */
432988ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
433006656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
433106656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
433206656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
433306656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4334d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4335d62866d3SStefano Zampini   if (n_vertices) {
4336d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4337d62866d3SStefano Zampini   }
4338d62866d3SStefano Zampini   if (n_constraints) {
4339d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4340d62866d3SStefano Zampini   }
434188ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
434288ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
434388ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4344d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
434588ebb749SStefano Zampini     Mat         coarse_sub_mat;
434625084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
434788ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
434888ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
434988ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
43508bec7fa6SStefano Zampini     Mat         C_B,CPHI;
43518bec7fa6SStefano Zampini     IS          is_dummy;
43528bec7fa6SStefano Zampini     Vec         mones;
435388ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
435488ebb749SStefano Zampini     PetscReal   real_value;
435588ebb749SStefano Zampini 
4356a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4357a3df083aSStefano Zampini       Mat A;
4358a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
43597dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
43607dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
43617dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
43627dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4363a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4364a3df083aSStefano Zampini     } else {
436588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
436688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
436788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
436888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4369a3df083aSStefano Zampini     }
437088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
437188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4372ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
437388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
437488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
437588ebb749SStefano Zampini     }
437688ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
437788ebb749SStefano Zampini 
437825084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
43793301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
438025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4381ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
438288ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
438388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
438488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
438588ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
438688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
438788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
438888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
438988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
439088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
439188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
439288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
439388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
439488ebb749SStefano Zampini     } else {
439588ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
439688ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
439788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
439888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
439988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
440088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
440188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
440288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
440388ebb749SStefano Zampini     }
440488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
440588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
440688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4407511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
44084f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4409fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4410d12edf2fSStefano Zampini       PetscScalar *data,*data2;
44114f1b2e48SStefano Zampini       PetscInt    j;
4412d12edf2fSStefano Zampini 
44134f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44147dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4415d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
441686c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4417d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4418d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
44194f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
44204f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4421d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
44224f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
44234f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
44244f1b2e48SStefano Zampini         }
4425d12edf2fSStefano Zampini       }
4426d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4427d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4428d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4429d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4430d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4431d12edf2fSStefano Zampini     }
4432d12edf2fSStefano Zampini #if 0
4433d12edf2fSStefano Zampini   {
4434d12edf2fSStefano Zampini     PetscViewer viewer;
4435d12edf2fSStefano Zampini     char filename[256];
4436ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4437d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4438a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4439ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4440ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4441ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4442d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4443a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4444ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4445ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
444672b8c272SStefano Zampini     }
4447ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4448ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4449ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4450ffd830a3SStefano Zampini     }
4451ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4452ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4453ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4454ffd830a3SStefano Zampini     }
445572b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4456ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4457ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4458ffd830a3SStefano Zampini     }
4459fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4460fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4461fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4462fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4463fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4464fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4465fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4466fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4467fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4468fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4469d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4470d12edf2fSStefano Zampini   }
4471d12edf2fSStefano Zampini #endif
447281d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
44738bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
44741575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
447506656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
44768bec7fa6SStefano Zampini 
44778bec7fa6SStefano Zampini     /* check constraints */
4478a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44797dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
44804f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
44818bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4482a00504b5SStefano Zampini     } else {
4483a00504b5SStefano Zampini       PetscScalar *data;
4484a00504b5SStefano Zampini       Mat         tmat;
4485a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4486a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4487a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4488a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4489a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4490a00504b5SStefano Zampini     }
44918bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
44928bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
44938bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
44948bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4495bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4496ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4497bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4498bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4499bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4500bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4501bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
450288ebb749SStefano Zampini     }
45038bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
45048bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
45058bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
45068bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
450725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
450888ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
450988ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
451088ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
451188ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
451288ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
451388ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
451488ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
451588ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
451688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
451788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4518ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
451988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
452088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
452188ebb749SStefano Zampini     }
452288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
452388ebb749SStefano Zampini   }
45248629588bSStefano Zampini   /* get back data */
45258629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
452688ebb749SStefano Zampini   PetscFunctionReturn(0);
452788ebb749SStefano Zampini }
452888ebb749SStefano Zampini 
45297dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4530aa0d41d4SStefano Zampini {
4531d65f70fdSStefano Zampini   Mat            *work_mat;
4532d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4533d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4534c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4535aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4536aa0d41d4SStefano Zampini 
4537aa0d41d4SStefano Zampini   PetscFunctionBegin;
4538d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4539d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4540d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4541d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4542aa0d41d4SStefano Zampini 
4543d65f70fdSStefano Zampini   if (!rsorted) {
4544906d46d4SStefano Zampini     const PetscInt *idxs;
4545906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4546aa0d41d4SStefano Zampini 
4547d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4548d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4549d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4550d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4551aa0d41d4SStefano Zampini     }
4552d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4553d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4554d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4555d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4556aa0d41d4SStefano Zampini     }
4557d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4558d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4559d65f70fdSStefano Zampini   } else {
4560d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4561d65f70fdSStefano Zampini     isrow_s = isrow;
4562aa0d41d4SStefano Zampini   }
4563906d46d4SStefano Zampini 
4564d65f70fdSStefano Zampini   if (!csorted) {
4565d65f70fdSStefano Zampini     if (isrow == iscol) {
4566d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4567d65f70fdSStefano Zampini       iscol_s = isrow_s;
4568d65f70fdSStefano Zampini     } else {
4569d65f70fdSStefano Zampini       const PetscInt *idxs;
4570d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4571906d46d4SStefano Zampini 
4572d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4573d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4574d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4575d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4576d65f70fdSStefano Zampini       }
4577d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4578d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4579d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4580d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4581d65f70fdSStefano Zampini       }
4582d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4583d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4584d65f70fdSStefano Zampini     }
4585d65f70fdSStefano Zampini   } else {
4586d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4587d65f70fdSStefano Zampini     iscol_s = iscol;
4588d65f70fdSStefano Zampini   }
4589d65f70fdSStefano Zampini 
45907dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4591d65f70fdSStefano Zampini 
4592d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4593906d46d4SStefano Zampini     Mat      new_mat;
4594d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4595906d46d4SStefano Zampini 
4596d65f70fdSStefano Zampini     if (!rsorted) {
4597d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4598d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4599d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4600d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4601906d46d4SStefano Zampini       }
4602d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4603d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4604d65f70fdSStefano Zampini     } else {
4605d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4606906d46d4SStefano Zampini     }
4607d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4608d65f70fdSStefano Zampini 
4609d65f70fdSStefano Zampini     if (!csorted) {
4610d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4611d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4612d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4613d65f70fdSStefano Zampini       } else {
4614d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4615f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4616d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4617d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4618d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4619d65f70fdSStefano Zampini         }
4620d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4621d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4622d65f70fdSStefano Zampini       }
4623d65f70fdSStefano Zampini     } else {
4624d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4625d65f70fdSStefano Zampini     }
4626d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4627d65f70fdSStefano Zampini 
4628d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4629d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4630d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4631d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4632d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4633d65f70fdSStefano Zampini   }
4634d65f70fdSStefano Zampini 
4635d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4636d65f70fdSStefano Zampini   *B = work_mat[0];
4637d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4638d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4639d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4640d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4641d65f70fdSStefano Zampini }
4642d65f70fdSStefano Zampini 
46435e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4644aa0d41d4SStefano Zampini {
4645aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
46465e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4647022d8d2bSstefano_zampini   Mat            new_mat,lA;
46485e8657edSStefano Zampini   IS             is_local,is_global;
4649d65f70fdSStefano Zampini   PetscInt       local_size;
4650d65f70fdSStefano Zampini   PetscBool      isseqaij;
4651aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4652aa0d41d4SStefano Zampini 
4653aa0d41d4SStefano Zampini   PetscFunctionBegin;
4654aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
46555e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
46565e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4657b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4658aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
46597dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4660aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4661906d46d4SStefano Zampini 
4662906d46d4SStefano Zampini   /* check */
4663906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4664906d46d4SStefano Zampini     Vec       x,x_change;
4665906d46d4SStefano Zampini     PetscReal error;
4666906d46d4SStefano Zampini 
46675e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4668906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
46695e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4670e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4671e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4672d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
467388428137SStefano Zampini     if (!pcbddc->change_interior) {
467488428137SStefano Zampini       const PetscScalar *x,*y,*v;
467588428137SStefano Zampini       PetscReal         lerror = 0.;
467688428137SStefano Zampini       PetscInt          i;
467788428137SStefano Zampini 
467888428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
467988428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
468088428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
468188428137SStefano Zampini       for (i=0;i<local_size;i++)
468288428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
468388428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
468488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
468588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
468688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
468788428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4688637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4689637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4690637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4691637e8532SStefano Zampini         } else {
4692637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4693637e8532SStefano Zampini         }
4694637e8532SStefano Zampini       }
469588428137SStefano Zampini     }
4696e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4697e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4698906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4699906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4700637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4701637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4702637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4703637e8532SStefano Zampini       } else {
4704637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4705637e8532SStefano Zampini       }
4706637e8532SStefano Zampini     }
4707906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4708906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4709906d46d4SStefano Zampini   }
4710906d46d4SStefano Zampini 
4711022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4712022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4713022d8d2bSstefano_zampini 
471422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
47159b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
471622d5777bSStefano Zampini   if (isseqaij) {
4717a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4718a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4719022d8d2bSstefano_zampini     if (lA) {
4720022d8d2bSstefano_zampini       Mat work;
4721022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4722022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4723022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4724022d8d2bSstefano_zampini     }
4725aa0d41d4SStefano Zampini   } else {
4726a00504b5SStefano Zampini     Mat work_mat;
47271cf9b237SStefano Zampini 
4728a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4729aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4730a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
47311d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4732022d8d2bSstefano_zampini     if (lA) {
4733022d8d2bSstefano_zampini       Mat work;
4734022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4735022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4736022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4737022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4738022d8d2bSstefano_zampini     }
4739aa0d41d4SStefano Zampini   }
47403301b35fSStefano Zampini   if (matis->A->symmetric_set) {
47413301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4742e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
47433301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4744e496cd5dSStefano Zampini #endif
47453301b35fSStefano Zampini   }
4746d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4747aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4748aa0d41d4SStefano Zampini }
4749aa0d41d4SStefano Zampini 
47508ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4751a64d13efSStefano Zampini {
4752a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4753a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4754d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
475553892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
47563a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
47573a50541eSStefano Zampini   PetscInt        vbs,bs;
47586816873aSStefano Zampini   PetscBT         bitmask=NULL;
4759a64d13efSStefano Zampini   PetscErrorCode  ierr;
4760a64d13efSStefano Zampini 
4761a64d13efSStefano Zampini   PetscFunctionBegin;
4762b23d619eSStefano Zampini   /*
4763b23d619eSStefano Zampini     No need to setup local scatters if
4764b23d619eSStefano Zampini       - primal space is unchanged
4765b23d619eSStefano Zampini         AND
4766b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4767b23d619eSStefano Zampini         AND
4768b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4769b23d619eSStefano Zampini   */
4770b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4771f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4772f4ddd8eeSStefano Zampini   }
4773f4ddd8eeSStefano Zampini   /* destroy old objects */
4774f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4775f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4776f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4777a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4778b371cd4fSStefano Zampini   n_B = pcis->n_B;
4779b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4780b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
47813a50541eSStefano Zampini 
4782a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
47836816873aSStefano Zampini 
478453892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4785b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4786854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4787a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4788a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
47890e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4790a64d13efSStefano Zampini     }
4791a64d13efSStefano Zampini 
4792a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
47934641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
47946816873aSStefano Zampini         idx_R_local[n_R++] = i;
4795a64d13efSStefano Zampini       }
4796a64d13efSStefano Zampini     }
4797df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4798df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
47996816873aSStefano Zampini 
4800df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4801df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
48026816873aSStefano Zampini   }
48033a50541eSStefano Zampini 
48043a50541eSStefano Zampini   /* Block code */
48053a50541eSStefano Zampini   vbs = 1;
48063a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
48073a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
48083a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
48093a50541eSStefano Zampini     PetscInt  *vary;
4810b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4811785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
48123a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4813d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4814d3df7717SStefano 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 */
48150e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4816d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
48173a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
48183a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
48193a50541eSStefano Zampini           break;
48203a50541eSStefano Zampini         }
48213a50541eSStefano Zampini       }
4822d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4823d3df7717SStefano Zampini     } else {
4824d3df7717SStefano Zampini       /* Verify directly the R set */
4825d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4826d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4827d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4828d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4829d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4830d3df7717SStefano Zampini             break;
4831d3df7717SStefano Zampini           }
4832d3df7717SStefano Zampini         }
4833d3df7717SStefano Zampini       }
4834d3df7717SStefano Zampini     }
48353a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
48363a50541eSStefano Zampini       vbs = bs;
48373a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
48383a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
48393a50541eSStefano Zampini       }
48403a50541eSStefano Zampini     }
48413a50541eSStefano Zampini   }
48423a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4843b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4844df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
484553892102SStefano Zampini 
4846df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4847df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
484853892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4849df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
485053892102SStefano Zampini   } else {
48513a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
485253892102SStefano Zampini   }
4853a64d13efSStefano Zampini 
4854a64d13efSStefano Zampini   /* print some info if requested */
4855a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4856a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4857a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
48581575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4859a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4860a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
48614f1b2e48SStefano 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);
4862a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4863a64d13efSStefano Zampini   }
4864a64d13efSStefano Zampini 
4865a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4866b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
48676816873aSStefano Zampini     IS       is_aux1,is_aux2;
48686816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
48696816873aSStefano Zampini 
48703a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4871854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4872854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4873a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
48744641a718SStefano Zampini     for (i=0; i<n_D; i++) {
48754641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
48764641a718SStefano Zampini     }
4877a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4878a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
48794641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
48804641a718SStefano Zampini         aux_array1[j++] = i;
4881a64d13efSStefano Zampini       }
4882a64d13efSStefano Zampini     }
4883a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4884a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4885a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
48864641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
48874641a718SStefano Zampini         aux_array2[j++] = i;
4888a64d13efSStefano Zampini       }
4889a64d13efSStefano Zampini     }
4890a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4891a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4892a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4893a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4894a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4895a64d13efSStefano Zampini 
48968eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4897785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4898a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
48994641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
49004641a718SStefano Zampini           aux_array1[j++] = i;
4901a64d13efSStefano Zampini         }
4902a64d13efSStefano Zampini       }
4903a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4904a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4905a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4906a64d13efSStefano Zampini     }
49074641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
49083a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4909d62866d3SStefano Zampini   } else {
4910df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
49116816873aSStefano Zampini     IS                 tis;
49126816873aSStefano Zampini     PetscInt           schur_size;
49136816873aSStefano Zampini 
4914df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
49156816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4916df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
49176816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
49186816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
49196816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
49206816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
49216816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4922d62866d3SStefano Zampini     }
4923d62866d3SStefano Zampini   }
4924a64d13efSStefano Zampini   PetscFunctionReturn(0);
4925a64d13efSStefano Zampini }
4926a64d13efSStefano Zampini 
4927304d26faSStefano Zampini 
4928684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4929304d26faSStefano Zampini {
4930304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4931304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4932304d26faSStefano Zampini   PC             pc_temp;
4933304d26faSStefano Zampini   Mat            A_RR;
4934f4ddd8eeSStefano Zampini   MatReuse       reuse;
4935304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4936304d26faSStefano Zampini   PetscReal      value;
493704708bb6SStefano Zampini   PetscInt       n_D,n_R;
493835529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
4939304d26faSStefano Zampini   PetscErrorCode ierr;
4940e604994aSStefano Zampini   /* prefixes stuff */
4941312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4942e604994aSStefano Zampini   size_t         len;
4943304d26faSStefano Zampini 
4944304d26faSStefano Zampini   PetscFunctionBegin;
4945304d26faSStefano Zampini 
4946e604994aSStefano Zampini   /* compute prefixes */
4947e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4948e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4949e604994aSStefano Zampini   if (!pcbddc->current_level) {
4950e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4951e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4952e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4953e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4954e604994aSStefano Zampini   } else {
495535529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
4956e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4957e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4958312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4959312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
496034d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
496134d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4962e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4963e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4964e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4965e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4966e604994aSStefano Zampini   }
4967e604994aSStefano Zampini 
4968304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4969684f6988SStefano Zampini   if (dirichlet) {
4970d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4971450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
49729a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4973450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4974a3df083aSStefano Zampini         Mat    A_IIn;
4975a3df083aSStefano Zampini 
4976a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4977a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4978a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4979a3df083aSStefano Zampini       }
4980450f8f5eSStefano Zampini     }
49813301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
49823301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4983964fefecSStefano Zampini     }
4984ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4985964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4986304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4987304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4988304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4989304d26faSStefano Zampini       /* default */
4990304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4991e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
49929577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4993304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
49949577ea80SStefano Zampini       if (issbaij) {
49959577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
49969577ea80SStefano Zampini       } else {
4997304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
49989577ea80SStefano Zampini       }
4999304d26faSStefano Zampini       /* Allow user's customization */
5000304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5001304d26faSStefano Zampini     }
5002d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5003b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5004df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5005d62866d3SStefano Zampini 
5006df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5007d5574798SStefano Zampini     }
5008304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5009304d26faSStefano Zampini     if (!n_D) {
5010304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5011304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5012304d26faSStefano Zampini     }
5013304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
5014304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
5015304d26faSStefano Zampini     /* set ksp_D into pcis data */
5016304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5017304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5018304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5019684f6988SStefano Zampini   }
5020304d26faSStefano Zampini 
5021304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5022684f6988SStefano Zampini   A_RR = 0;
5023684f6988SStefano Zampini   if (neumann) {
5024d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
502504708bb6SStefano Zampini     PetscInt        ibs,mbs;
50260aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
502704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
50280aa714b2SStefano Zampini 
50290aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
50300aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
50310aa714b2SStefano Zampini       IS iP;
50320aa714b2SStefano Zampini 
50330aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
50340aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
50350aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
50360aa714b2SStefano Zampini     }
5037f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
50388ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5039f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5040f4ddd8eeSStefano Zampini       PetscInt nn_R;
504181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5042f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5043f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5044f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5045f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5046f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5047f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5048f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5049727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5050f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5051f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5052f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5053f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5054f4ddd8eeSStefano Zampini         }
5055f4ddd8eeSStefano Zampini       }
5056f4ddd8eeSStefano Zampini       /* last check */
5057d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5058f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5059f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5060f4ddd8eeSStefano Zampini       }
5061f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5062f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5063f4ddd8eeSStefano Zampini     }
5064a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5065af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5066af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
506704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
506804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
506904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
507004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
507104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5072af732b37SStefano Zampini       } else {
5073511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
50746816873aSStefano Zampini       }
507504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
507604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
507704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
507804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
507904708bb6SStefano Zampini       } else {
5080511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
508104708bb6SStefano Zampini       }
508204708bb6SStefano Zampini     }
5083a00504b5SStefano Zampini     /* extract A_RR */
50840aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5085a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5086a00504b5SStefano Zampini 
5087a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
508816e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5089a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
509016e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
509116e386b8SStefano Zampini         } else {
50927dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5093a00504b5SStefano Zampini         }
5094a00504b5SStefano Zampini       } else {
5095a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5096a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5097a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5098a00504b5SStefano Zampini       }
5099a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
51007dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
510116e386b8SStefano Zampini     }
51023301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
51033301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
51046816873aSStefano Zampini     }
5105f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5106304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5107304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5108304d26faSStefano Zampini       /* default */
5109304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5110e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5111304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
51129577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
51139577ea80SStefano Zampini       if (issbaij) {
51149577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
51159577ea80SStefano Zampini       } else {
5116304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
51179577ea80SStefano Zampini       }
5118304d26faSStefano Zampini       /* Allow user's customization */
5119304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5120304d26faSStefano Zampini     }
5121304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5122304d26faSStefano Zampini     if (!n_R) {
5123304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5124304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5125304d26faSStefano Zampini     }
51265cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5127df4d28bfSStefano Zampini     /* Reuse solver if it is present */
51280aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5129df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5130d62866d3SStefano Zampini 
5131df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5132d62866d3SStefano Zampini     }
5133304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
5134304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
5135684f6988SStefano Zampini   }
5136304d26faSStefano Zampini 
5137684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5138684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51391575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5140684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5141684f6988SStefano Zampini   }
5142c7017625SStefano Zampini 
5143c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
514435529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5145c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5146c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5147c7017625SStefano Zampini   }
5148c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
514935529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5150c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5151c7017625SStefano Zampini   }
5152c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
515335529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5154c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5155c7017625SStefano Zampini   }
5156c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5157c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5158684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
51590fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
51600fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
51610fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
51620fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
51630fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5164e604994aSStefano 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);
516535529e7bSStefano Zampini       if (check_corr) {
5166c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5167c7017625SStefano Zampini       }
5168304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5169304d26faSStefano Zampini     }
5170684f6988SStefano Zampini     if (neumann) { /* Neumann */
51710fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
51720fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
51730fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
51740fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
51750fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5176e604994aSStefano 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);
517735529e7bSStefano Zampini       if (check_corr) {
5178c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5179c7017625SStefano Zampini       }
5180304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5181304d26faSStefano Zampini     }
5182684f6988SStefano Zampini   }
51835cbda25cSStefano Zampini   /* free Neumann problem's matrix */
51845cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5185304d26faSStefano Zampini   PetscFunctionReturn(0);
5186304d26faSStefano Zampini }
5187304d26faSStefano Zampini 
518880677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5189674ae819SStefano Zampini {
5190674ae819SStefano Zampini   PetscErrorCode  ierr;
5191674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5192be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5193b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5194674ae819SStefano Zampini 
5195674ae819SStefano Zampini   PetscFunctionBegin;
5196b334f244SStefano Zampini   if (!reuse_solver) {
519780677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
519820c7b377SStefano Zampini   }
519980677318SStefano Zampini   if (!pcbddc->switch_static) {
520080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
520180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
520280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
520320c7b377SStefano Zampini     }
5204b334f244SStefano Zampini     if (!reuse_solver) {
520580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
520680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
520720c7b377SStefano Zampini     } else {
5208df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5209be83ff47SStefano Zampini 
5210df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5211df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
521220c7b377SStefano Zampini     }
5213be83ff47SStefano Zampini   } else {
521480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
521580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
521680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
521780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
521880677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
521980677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
522080677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
522180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
522280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5223674ae819SStefano Zampini     }
5224674ae819SStefano Zampini   }
5225b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
522680677318SStefano Zampini     if (applytranspose) {
522780677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
522880677318SStefano Zampini     } else {
522980677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
523080677318SStefano Zampini     }
5231be83ff47SStefano Zampini   } else {
5232df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5233be83ff47SStefano Zampini 
5234be83ff47SStefano Zampini     if (applytranspose) {
5235df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5236be83ff47SStefano Zampini     } else {
5237df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5238be83ff47SStefano Zampini     }
5239be83ff47SStefano Zampini   }
524080677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
524180677318SStefano Zampini   if (!pcbddc->switch_static) {
5242b334f244SStefano Zampini     if (!reuse_solver) {
524380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
524480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5245be83ff47SStefano Zampini     } else {
5246df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5247be83ff47SStefano Zampini 
5248df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5249df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5250be83ff47SStefano Zampini     }
525180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
525280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
525380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
525480677318SStefano Zampini     }
525580677318SStefano Zampini   } else {
525680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
525780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
525880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
525980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
526080677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
526180677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
526280677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
526380677318SStefano Zampini     }
526480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
526580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
526680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
526780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5268674ae819SStefano Zampini   }
5269674ae819SStefano Zampini   PetscFunctionReturn(0);
5270674ae819SStefano Zampini }
5271674ae819SStefano Zampini 
5272dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5273dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5274674ae819SStefano Zampini {
5275674ae819SStefano Zampini   PetscErrorCode ierr;
5276674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5277674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5278674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5279674ae819SStefano Zampini 
5280674ae819SStefano Zampini   PetscFunctionBegin;
5281dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
52824fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5283dc359a40SStefano Zampini     if (applytranspose) {
5284674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
52858eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5286dc359a40SStefano Zampini     } else {
5287674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5288674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
528915aaf578SStefano Zampini     }
52904fee134fSStefano Zampini   } else {
52914fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
52924fee134fSStefano Zampini   }
5293efc2fbd9SStefano Zampini 
5294efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
52954f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5296efc2fbd9SStefano Zampini     PetscScalar *array;
52974f1b2e48SStefano Zampini     PetscInt    j;
5298efc2fbd9SStefano Zampini 
5299efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
53004f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5301efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5302efc2fbd9SStefano Zampini   }
5303efc2fbd9SStefano Zampini 
530412edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
530512edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
530612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
530712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
530812edc857SStefano Zampini 
53099f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
531012edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
531151694757SStefano Zampini     Mat          coarse_mat;
5312964fefecSStefano Zampini     Vec          rhs,sol;
531351694757SStefano Zampini     MatNullSpace nullsp;
531427b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5315964fefecSStefano Zampini 
531627b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
531727b6a85dSStefano Zampini       PC        coarse_pc;
531827b6a85dSStefano Zampini 
531927b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
532027b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
532127b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
532227b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
532327b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
532427b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
53253bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
532627b6a85dSStefano Zampini       }
532727b6a85dSStefano Zampini     }
5328964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5329964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
533051694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
533151694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
533251694757SStefano Zampini     if (nullsp) {
533351694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
533451694757SStefano Zampini     }
533512edc857SStefano Zampini     if (applytranspose) {
53369a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5337964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
53382701bc32SStefano Zampini     } else {
53391f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
53402701bc32SStefano Zampini         PC        coarse_pc;
53412701bc32SStefano Zampini 
53422701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
53432701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
53443e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
53452701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
534612edc857SStefano Zampini       } else {
5347964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
534812edc857SStefano Zampini       }
53492701bc32SStefano Zampini     }
53501d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
535127b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
535227b6a85dSStefano Zampini       PC        coarse_pc;
535327b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
535427b6a85dSStefano Zampini 
535527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
535627b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
535727b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
53583bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
535927b6a85dSStefano Zampini     }
536051694757SStefano Zampini     if (nullsp) {
536151694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
536251694757SStefano Zampini     }
536312edc857SStefano Zampini   }
5364674ae819SStefano Zampini 
5365674ae819SStefano Zampini   /* Local solution on R nodes */
53664fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
536780677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
53689f00e9b4SStefano Zampini   }
53699f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
53709f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
537112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5372674ae819SStefano Zampini 
53734fee134fSStefano Zampini   /* Sum contributions from the two levels */
53744fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5375dc359a40SStefano Zampini     if (applytranspose) {
5376dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5377dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5378dc359a40SStefano Zampini     } else {
5379674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
53808eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5381dc359a40SStefano Zampini     }
5382efc2fbd9SStefano Zampini     /* store p0 */
53834f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5384efc2fbd9SStefano Zampini       PetscScalar *array;
53854f1b2e48SStefano Zampini       PetscInt    j;
5386efc2fbd9SStefano Zampini 
5387efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
53884f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5389efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5390efc2fbd9SStefano Zampini     }
53914fee134fSStefano Zampini   } else { /* expand the coarse solution */
53924fee134fSStefano Zampini     if (applytranspose) {
53934fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
53944fee134fSStefano Zampini     } else {
53954fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
53964fee134fSStefano Zampini     }
53974fee134fSStefano Zampini   }
5398674ae819SStefano Zampini   PetscFunctionReturn(0);
5399674ae819SStefano Zampini }
5400674ae819SStefano Zampini 
540112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5402674ae819SStefano Zampini {
5403674ae819SStefano Zampini   PetscErrorCode ierr;
5404674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
540558da7f69SStefano Zampini   PetscScalar    *array;
540612edc857SStefano Zampini   Vec            from,to;
5407674ae819SStefano Zampini 
5408674ae819SStefano Zampini   PetscFunctionBegin;
540912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
541012edc857SStefano Zampini     from = pcbddc->coarse_vec;
541112edc857SStefano Zampini     to = pcbddc->vec1_P;
541212edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
541312edc857SStefano Zampini       Vec tvec;
541458da7f69SStefano Zampini 
541558da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
541658da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
541712edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
541858da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
541958da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
542058da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
542112edc857SStefano Zampini     }
542212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
542312edc857SStefano Zampini     from = pcbddc->vec1_P;
542412edc857SStefano Zampini     to = pcbddc->coarse_vec;
542512edc857SStefano Zampini   }
542612edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5427674ae819SStefano Zampini   PetscFunctionReturn(0);
5428674ae819SStefano Zampini }
5429674ae819SStefano Zampini 
543012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5431674ae819SStefano Zampini {
5432674ae819SStefano Zampini   PetscErrorCode ierr;
5433674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
543458da7f69SStefano Zampini   PetscScalar    *array;
543512edc857SStefano Zampini   Vec            from,to;
5436674ae819SStefano Zampini 
5437674ae819SStefano Zampini   PetscFunctionBegin;
543812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
543912edc857SStefano Zampini     from = pcbddc->coarse_vec;
544012edc857SStefano Zampini     to = pcbddc->vec1_P;
544112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
544212edc857SStefano Zampini     from = pcbddc->vec1_P;
544312edc857SStefano Zampini     to = pcbddc->coarse_vec;
544412edc857SStefano Zampini   }
544512edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
544612edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
544712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
544812edc857SStefano Zampini       Vec tvec;
544958da7f69SStefano Zampini 
545012edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
545158da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
545258da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
545358da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
545458da7f69SStefano Zampini     }
545558da7f69SStefano Zampini   } else {
545658da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
545758da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
545812edc857SStefano Zampini     }
545912edc857SStefano Zampini   }
5460674ae819SStefano Zampini   PetscFunctionReturn(0);
5461674ae819SStefano Zampini }
5462674ae819SStefano Zampini 
5463984c4197SStefano Zampini /* uncomment for testing purposes */
5464984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5465674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5466674ae819SStefano Zampini {
5467674ae819SStefano Zampini   PetscErrorCode    ierr;
5468674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5469674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5470674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5471984c4197SStefano Zampini   /* one and zero */
5472984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5473984c4197SStefano Zampini   /* space to store constraints and their local indices */
54749162d606SStefano Zampini   PetscScalar       *constraints_data;
54759162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
54769162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
54779162d606SStefano Zampini   PetscInt          *constraints_n;
5478984c4197SStefano Zampini   /* iterators */
5479b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5480984c4197SStefano Zampini   /* BLAS integers */
5481e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5482e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5483c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5484727cdba6SStefano Zampini   /* reuse */
54850e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
54860e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5487984c4197SStefano Zampini   /* change of basis */
5488b3d85658SStefano Zampini   PetscBool         qr_needed;
54899162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5490984c4197SStefano Zampini   /* auxiliary stuff */
549164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
54928a0068c3SStefano Zampini   PetscInt          ncc;
5493984c4197SStefano Zampini   /* some quantities */
549445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5495a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
5496984c4197SStefano Zampini 
5497674ae819SStefano Zampini   PetscFunctionBegin;
54988e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
54998e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
55008e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
550116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5502088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5503088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
55040e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
55050e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
55060e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
55070e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
55080e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5509088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5510cf5a6209SStefano Zampini 
5511cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
55129162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5513cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5514cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5515cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5516cf5a6209SStefano Zampini     PetscScalar  *array;
5517cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5518cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5519674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5520b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5521674ae819SStefano Zampini     PetscScalar  *work;
5522674ae819SStefano Zampini     PetscReal    *singular_vals;
5523674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5524674ae819SStefano Zampini     PetscReal    *rwork;
5525674ae819SStefano Zampini #endif
5526674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5527674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5528674ae819SStefano Zampini #else
5529964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5530964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5531674ae819SStefano Zampini #endif
5532674ae819SStefano Zampini 
5533674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5534d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5535e4d548c7SStefano Zampini     /* print some info */
55365c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5537e4d548c7SStefano Zampini       PetscInt nv;
5538e4d548c7SStefano Zampini 
5539c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5540e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5541e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5542e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5543e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5544e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5545e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5546e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5547e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5548e4d548c7SStefano Zampini     }
5549e4d548c7SStefano Zampini 
5550d06fc5fdSStefano Zampini     /* free unneeded index sets */
5551d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5552d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5553674ae819SStefano Zampini     }
5554d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5555d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5556d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5557d06fc5fdSStefano Zampini       }
5558d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5559d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5560d06fc5fdSStefano Zampini     }
5561d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5562d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5563d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5564d06fc5fdSStefano Zampini       }
5565d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5566d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5567d06fc5fdSStefano Zampini     }
556870022509SStefano Zampini 
5569674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5570674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5571674ae819SStefano Zampini     if (nearnullsp) {
5572674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5573f4ddd8eeSStefano Zampini       /* remove any stored info */
5574f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5575f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5576f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5577f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5578f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5579473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5580f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5581f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5582f4ddd8eeSStefano Zampini       }
5583984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5584984c4197SStefano Zampini       nnsp_size = 0;
5585674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5586674ae819SStefano Zampini     }
5587984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5588984c4197SStefano Zampini     max_constraints = nnsp_size;
5589984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5590984c4197SStefano Zampini 
5591674ae819SStefano Zampini     /*
5592674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
55939162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
55949162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
55959162d606SStefano Zampini          There can be multiple constraints per connected component
5596674ae819SStefano Zampini                                                                                                                                                            */
5597674ae819SStefano Zampini     n_vertices = 0;
5598674ae819SStefano Zampini     if (ISForVertices) {
5599674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5600674ae819SStefano Zampini     }
56019162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
56029162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
56039162d606SStefano Zampini 
56049162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
56059162d606SStefano Zampini     total_counts *= max_constraints;
5606674ae819SStefano Zampini     total_counts += n_vertices;
56074641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
56089162d606SStefano Zampini 
5609674ae819SStefano Zampini     total_counts = 0;
5610674ae819SStefano Zampini     max_size_of_constraint = 0;
5611674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
56129162d606SStefano Zampini       IS used_is;
5613674ae819SStefano Zampini       if (i<n_ISForEdges) {
56149162d606SStefano Zampini         used_is = ISForEdges[i];
5615674ae819SStefano Zampini       } else {
56169162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5617674ae819SStefano Zampini       }
56189162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5619674ae819SStefano Zampini       total_counts += j;
5620674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5621674ae819SStefano Zampini     }
56229162d606SStefano 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);
56239162d606SStefano Zampini 
5624984c4197SStefano Zampini     /* get local part of global near null space vectors */
5625785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5626984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5627984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5628e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5629e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5630984c4197SStefano Zampini     }
5631674ae819SStefano Zampini 
5632242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5633242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5634a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5635242a89d7SStefano Zampini 
5636984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5637a773dcb8SStefano Zampini     if (!skip_lapack) {
5638674ae819SStefano Zampini       PetscScalar temp_work;
5639911cabfeSStefano Zampini 
5640674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5641984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5642785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5643785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5644785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5645674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5646785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5647674ae819SStefano Zampini #endif
5648674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5649c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5650c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5651674ae819SStefano Zampini       lwork = -1;
5652674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5653674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5654c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5655674ae819SStefano Zampini #else
5656c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5657674ae819SStefano Zampini #endif
5658674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5659984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5660674ae819SStefano Zampini #else /* on missing GESVD */
5661674ae819SStefano Zampini       /* SVD */
5662674ae819SStefano Zampini       PetscInt max_n,min_n;
5663674ae819SStefano Zampini       max_n = max_size_of_constraint;
5664984c4197SStefano Zampini       min_n = max_constraints;
5665984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5666674ae819SStefano Zampini         min_n = max_size_of_constraint;
5667984c4197SStefano Zampini         max_n = max_constraints;
5668674ae819SStefano Zampini       }
5669785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5670674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5671785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5672674ae819SStefano Zampini #endif
5673674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5674674ae819SStefano Zampini       lwork = -1;
5675e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5676e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5677b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5678674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5679674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
56809162d606SStefano 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));
5681674ae819SStefano Zampini #else
56829162d606SStefano 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));
5683674ae819SStefano Zampini #endif
5684674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5685984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5686984c4197SStefano Zampini #endif /* on missing GESVD */
5687674ae819SStefano Zampini       /* Allocate optimal workspace */
5688674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5689854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5690674ae819SStefano Zampini     }
5691674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5692674ae819SStefano Zampini     total_counts = 0;
56939162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
56949162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5695674ae819SStefano Zampini     /* vertices */
56969162d606SStefano Zampini     if (n_vertices) {
5697674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
56989162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5699674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
57009162d606SStefano Zampini         constraints_n[total_counts] = 1;
57019162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
57029162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
57039162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5704674ae819SStefano Zampini         total_counts++;
5705674ae819SStefano Zampini       }
5706674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5707674ae819SStefano Zampini       n_vertices = total_counts;
5708674ae819SStefano Zampini     }
5709984c4197SStefano Zampini 
5710674ae819SStefano Zampini     /* edges and faces */
57119162d606SStefano Zampini     total_counts_cc = total_counts;
5712911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
57139162d606SStefano Zampini       IS        used_is;
57149162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
57159162d606SStefano Zampini 
5716911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
57179162d606SStefano Zampini         used_is = ISForEdges[ncc];
5718984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5719674ae819SStefano Zampini       } else {
57209162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5721984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5722674ae819SStefano Zampini       }
5723674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
57249162d606SStefano Zampini 
57259162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
57269162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5727984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5728984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5729674ae819SStefano Zampini       if (nnsp_has_cnst) {
57305b08dc53SStefano Zampini         PetscScalar quad_value;
57319162d606SStefano Zampini 
57329162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
57339162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
57349162d606SStefano Zampini 
5735a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5736674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5737a773dcb8SStefano Zampini         } else {
5738a773dcb8SStefano Zampini           quad_value = 1.0;
5739a773dcb8SStefano Zampini         }
5740674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
57419162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5742674ae819SStefano Zampini         }
57439162d606SStefano Zampini         temp_constraints++;
5744674ae819SStefano Zampini         total_counts++;
5745674ae819SStefano Zampini       }
5746674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5747984c4197SStefano Zampini         PetscReal real_value;
57489162d606SStefano Zampini         PetscScalar *ptr_to_data;
57499162d606SStefano Zampini 
5750984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
57519162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5752674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
57539162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5754674ae819SStefano Zampini         }
5755984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5756984c4197SStefano Zampini         /* check if array is null on the connected component */
5757e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
57589162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
57595b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5760674ae819SStefano Zampini           temp_constraints++;
5761674ae819SStefano Zampini           total_counts++;
57629162d606SStefano Zampini           if (!idxs_copied) {
57639162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
57649162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5765674ae819SStefano Zampini           }
5766674ae819SStefano Zampini         }
57679162d606SStefano Zampini       }
57689162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
576945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5770eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5771a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
57729162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
57739162d606SStefano Zampini 
57749162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5775a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
57769162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5777a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
57789162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5779a773dcb8SStefano Zampini         } else { /* perform SVD */
5780984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
57819162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5782674ae819SStefano Zampini 
5783674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5784984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5785984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5786984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5787984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5788984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5789984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5790984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5791984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5792674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5793e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5794984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5795674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5796674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
57979162d606SStefano 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));
5798674ae819SStefano Zampini             }
5799674ae819SStefano Zampini           }
5800e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5801e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5802e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5803674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5804c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5805674ae819SStefano Zampini #else
5806c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5807674ae819SStefano Zampini #endif
5808674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5809984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5810984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5811674ae819SStefano Zampini           j = 0;
5812984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5813674ae819SStefano Zampini           total_counts = total_counts-j;
581445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5815e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5816c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5817c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5818c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5819c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5820c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5821c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5822674ae819SStefano Zampini           if (j<temp_constraints) {
5823984c4197SStefano Zampini             PetscInt ii;
5824984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5825674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58269162d606SStefano 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));
5827674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5828984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5829674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
58309162d606SStefano 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];
5831674ae819SStefano Zampini               }
5832674ae819SStefano Zampini             }
5833674ae819SStefano Zampini           }
5834674ae819SStefano Zampini #else  /* on missing GESVD */
5835e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5836e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5837b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5838674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5839674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
58409162d606SStefano 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));
5841674ae819SStefano Zampini #else
58429162d606SStefano 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));
5843674ae819SStefano Zampini #endif
5844984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5845674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5846984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5847e310c8b4SStefano Zampini           k = temp_constraints;
5848e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5849674ae819SStefano Zampini           j = 0;
5850e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
585145a1bb75SStefano Zampini           valid_constraints = k-j;
5852911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5853984c4197SStefano Zampini #endif /* on missing GESVD */
5854674ae819SStefano Zampini         }
5855a773dcb8SStefano Zampini       }
58569162d606SStefano Zampini       /* update pointers information */
58579162d606SStefano Zampini       if (valid_constraints) {
58589162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
58599162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
58609162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
58619162d606SStefano Zampini         /* set change_of_basis flag */
586245a1bb75SStefano Zampini         if (boolforchange) {
5863b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
58649162d606SStefano Zampini         }
5865b3d85658SStefano Zampini         total_counts_cc++;
586645a1bb75SStefano Zampini       }
586745a1bb75SStefano Zampini     }
5868984c4197SStefano Zampini     /* free workspace */
58698f1c130eSStefano Zampini     if (!skip_lapack) {
5870984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5871984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5872984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5873984c4197SStefano Zampini #endif
5874984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5875984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5876984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5877984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5878984c4197SStefano Zampini #endif
5879984c4197SStefano Zampini     }
5880984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5881984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5882984c4197SStefano Zampini     }
5883984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5884cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5885cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5886cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5887cf5a6209SStefano Zampini     }
5888cf5a6209SStefano Zampini     if (n_ISForFaces) {
5889cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5890cf5a6209SStefano Zampini     }
5891cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5892cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5893cf5a6209SStefano Zampini     }
5894cf5a6209SStefano Zampini     if (n_ISForEdges) {
5895cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5896cf5a6209SStefano Zampini     }
5897cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
589808122e43SStefano Zampini   } else {
589908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5900984c4197SStefano Zampini 
590108122e43SStefano Zampini     total_counts = 0;
590208122e43SStefano Zampini     n_vertices = 0;
5903d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5904d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
590508122e43SStefano Zampini     }
590608122e43SStefano Zampini     max_constraints = 0;
59079162d606SStefano Zampini     total_counts_cc = 0;
590808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
590908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
59109162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
591108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
591208122e43SStefano Zampini     }
59139162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
59149162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
59159162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
59169162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
591774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
59189162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
59199162d606SStefano Zampini     total_counts_cc = 0;
59209162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
59219162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
59229162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
592308122e43SStefano Zampini       }
592408122e43SStefano Zampini     }
59259162d606SStefano Zampini #if 0
59269162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
59279162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
59289162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
59299162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
59309162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
59319162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
59329162d606SStefano Zampini       }
59339162d606SStefano Zampini       printf("\n");
59349162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
59359162d606SStefano Zampini     }
59361b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
59378bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
59381b968477SStefano Zampini     }
59391b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
59408bec7fa6SStefano 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]);
59411b968477SStefano Zampini     }
594208122e43SStefano Zampini #endif
594308122e43SStefano Zampini 
59448bec7fa6SStefano Zampini     max_size_of_constraint = 0;
59459162d606SStefano 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]);
59469162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
594708122e43SStefano Zampini     /* Change of basis */
5948b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
594908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
595008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
595108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5952b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
595308122e43SStefano Zampini         }
595408122e43SStefano Zampini       }
595508122e43SStefano Zampini     }
595608122e43SStefano Zampini   }
5957984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
59584f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
595908122e43SStefano Zampini 
59609162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
59619162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
5962eee23b56SStefano 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);
5963674ae819SStefano Zampini 
5964674ae819SStefano Zampini   /* Create constraint matrix */
5965674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
596616f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5967984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5968984c4197SStefano Zampini 
5969984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5970a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5971a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
597274d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5973984c4197SStefano Zampini   total_primal_vertices=0;
5974b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
59759162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
59769162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
597772b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
59789162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5979b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
598064efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
59819162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
59829162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5983a717540cSStefano Zampini       }
5984b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
598591af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5986a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5987a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5988a717540cSStefano Zampini       }
5989fa434743SStefano Zampini     } else {
5990b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5991fa434743SStefano Zampini     }
5992a717540cSStefano Zampini   }
5993b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5994b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5995674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
599670022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
59974f1b2e48SStefano 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);
59980e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
59990e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6000984c4197SStefano Zampini 
6001984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
600274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6003785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6004984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
600574d5cdf7SStefano Zampini 
6006984c4197SStefano Zampini   j = total_primal_vertices;
600774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6008b3d85658SStefano Zampini   cum = total_primal_vertices;
60099162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
60104641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6011b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6012b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6013b3d85658SStefano Zampini       cum++;
60149162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
601574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
601674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
601774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
601874d5cdf7SStefano Zampini       }
60199162d606SStefano Zampini       j += constraints_n[i];
6020674ae819SStefano Zampini     }
6021674ae819SStefano Zampini   }
6022674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6023674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6024088faed8SStefano Zampini 
6025674ae819SStefano Zampini   /* set values in constraint matrix */
6026984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
60270e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6028674ae819SStefano Zampini   }
6029984c4197SStefano Zampini   total_counts = total_primal_vertices;
60309162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
60314641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
60329162d606SStefano Zampini       PetscInt *cols;
60339162d606SStefano Zampini 
60349162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
60359162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
60369162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
60379162d606SStefano Zampini         PetscInt    row = total_counts+k;
60389162d606SStefano Zampini         PetscScalar *vals;
60399162d606SStefano Zampini 
60409162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
60419162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
60429162d606SStefano Zampini       }
60439162d606SStefano Zampini       total_counts += constraints_n[i];
6044674ae819SStefano Zampini     }
6045674ae819SStefano Zampini   }
6046674ae819SStefano Zampini   /* assembling */
6047674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6048674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6049088faed8SStefano Zampini 
6050984c4197SStefano Zampini   /*
60516a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6052984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
6053f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
6054984c4197SStefano Zampini   */
6055674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6056674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6057026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6058984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6059984c4197SStefano Zampini     /* working stuff for GEQRF */
606081d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
6061984c4197SStefano Zampini     PetscBLASInt lqr_work;
6062984c4197SStefano Zampini     /* working stuff for UNGQR */
6063984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
6064984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6065984c4197SStefano Zampini     /* working stuff for TRTRS */
6066984c4197SStefano Zampini     PetscScalar  *trs_rhs;
60673f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6068984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6069984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6070984c4197SStefano Zampini     PetscScalar  *start_vals;
6071984c4197SStefano Zampini     /* working stuff for values insertion */
60724641a718SStefano Zampini     PetscBT      is_primal;
607364efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6074906d46d4SStefano Zampini     /* matrix sizes */
6075906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6076906d46d4SStefano Zampini     /* temporary change of basis */
6077906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6078cf5a6209SStefano Zampini     /* extra space for debugging */
6079cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
6080984c4197SStefano Zampini 
6081906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6082906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
608316f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6084bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6085906d46d4SStefano Zampini     /* nonzeros for local mat */
6086bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
60871dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6088bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
60891dd7afcfSStefano Zampini     } else {
60901dd7afcfSStefano Zampini       const PetscInt *ii;
60911dd7afcfSStefano Zampini       PetscInt       n;
60921dd7afcfSStefano Zampini       PetscBool      flg_row;
60931dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
60941dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
60951dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
60961dd7afcfSStefano Zampini     }
60979162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6098a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
60999162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6100a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
61019162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6102a717540cSStefano Zampini         } else {
61039162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
61049162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6105a717540cSStefano Zampini         }
6106a717540cSStefano Zampini       }
6107a717540cSStefano Zampini     }
6108906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6109bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
61101dd7afcfSStefano Zampini     /* Set interior change in the matrix */
61111dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6112bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6113906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6114a717540cSStefano Zampini       }
61151dd7afcfSStefano Zampini     } else {
61161dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
61171dd7afcfSStefano Zampini       PetscScalar    *aa;
61181dd7afcfSStefano Zampini       PetscInt       n;
61191dd7afcfSStefano Zampini       PetscBool      flg_row;
61201dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
61211dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
61221dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
61231dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
61241dd7afcfSStefano Zampini       }
61251dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
61261dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
61271dd7afcfSStefano Zampini     }
6128a717540cSStefano Zampini 
6129a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6130a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6131a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6132a717540cSStefano Zampini     }
6133a717540cSStefano Zampini 
6134a717540cSStefano Zampini 
6135a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6136a717540cSStefano Zampini     /*
6137a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6138a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6139a717540cSStefano Zampini 
6140a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6141a717540cSStefano Zampini 
6142a6b551f4SStefano 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)
6143a6b551f4SStefano Zampini 
6144a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6145a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6146a717540cSStefano Zampini             |              ...                        |
6147a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6148a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6149a717540cSStefano Zampini 
6150a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6151a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6152a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6153a6b551f4SStefano Zampini 
6154a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6155a717540cSStefano Zampini     */
6156a717540cSStefano Zampini     if (qr_needed) {
6157984c4197SStefano Zampini       /* space to store Q */
6158854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
61594e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
61604e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6161984c4197SStefano Zampini       /* first we issue queries for optimal work */
61623f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
61633f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
61643f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6165984c4197SStefano Zampini       lqr_work = -1;
61663f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6167984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6168984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6169785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6170984c4197SStefano Zampini       lgqr_work = -1;
61713f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
61723f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
61733f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
61743f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
61753f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6176c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6177c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6178984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6179785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6180984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6181785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6182a717540cSStefano Zampini       /* allocating workspace for check */
6183a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6184cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6185a717540cSStefano Zampini       }
6186a717540cSStefano Zampini     }
6187984c4197SStefano Zampini     /* array to store whether a node is primal or not */
61884641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6189473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
61900e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
6191eee23b56SStefano 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);
619239e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
619339e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
619439e2fb2aSStefano Zampini     }
619539e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6196984c4197SStefano Zampini 
6197a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
61989162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
61999162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
62004641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6201984c4197SStefano Zampini         /* get constraint info */
62029162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6203984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6204984c4197SStefano Zampini 
6205984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
62069162d606SStefano 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);
6207674ae819SStefano Zampini         }
6208984c4197SStefano Zampini 
6209fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6210a717540cSStefano Zampini 
6211a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6212a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
62139162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6214a717540cSStefano Zampini           }
6215984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
62169162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6217984c4197SStefano Zampini 
6218984c4197SStefano Zampini           /* compute QR decomposition of constraints */
62193f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62203f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62213f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6222674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62233f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6224984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6225674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6226984c4197SStefano Zampini 
6227984c4197SStefano Zampini           /* explictly compute R^-T */
6228984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6229984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
62303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62313f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
62323f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62333f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6234984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62353f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6236984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6237984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6238984c4197SStefano Zampini 
6239a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
62403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62413f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
62423f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
62433f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6244984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6245c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6246c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6247984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6248984c4197SStefano Zampini 
6249984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6250984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6251984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
62523f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62533f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62543f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
62553f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62563f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
62573f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6258984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62599162d606SStefano 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));
6260984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
62619162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6262984c4197SStefano Zampini 
6263984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
62649162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6265984c4197SStefano Zampini           /* insert cols for primal dofs */
6266984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6267984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
62689162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6269906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6270984c4197SStefano Zampini           }
6271984c4197SStefano Zampini           /* insert cols for dual dofs */
6272984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
62739162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6274984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
62759162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6276906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6277984c4197SStefano Zampini               j++;
6278674ae819SStefano Zampini             }
6279674ae819SStefano Zampini           }
6280984c4197SStefano Zampini 
6281984c4197SStefano Zampini           /* check change of basis */
6282984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6283984c4197SStefano Zampini             PetscInt   ii,jj;
6284984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6285c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6286c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6287c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6288c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6289c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6290c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6291984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6292cf5a6209SStefano 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));
6293984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6294984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6295984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6296cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6297c068d9bbSLisandro Dalcin                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) valid_qr = PETSC_FALSE;
6298674ae819SStefano Zampini               }
6299674ae819SStefano Zampini             }
6300984c4197SStefano Zampini             if (!valid_qr) {
630122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6302984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6303984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6304cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6305cf5a6209SStefano 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]));
6306674ae819SStefano Zampini                   }
6307c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
6308cf5a6209SStefano 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]));
6309984c4197SStefano Zampini                   }
6310984c4197SStefano Zampini                 }
6311984c4197SStefano Zampini               }
6312674ae819SStefano Zampini             } else {
631322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6314674ae819SStefano Zampini             }
6315674ae819SStefano Zampini           }
6316a717540cSStefano Zampini         } else { /* simple transformation block */
6317a717540cSStefano Zampini           PetscInt    row,col;
6318a6b551f4SStefano Zampini           PetscScalar val,norm;
6319a6b551f4SStefano Zampini 
6320a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63219162d606SStefano 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));
6322a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
63239162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
63249162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6325bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
63269162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6327906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
63289162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6329a717540cSStefano Zampini             } else {
6330a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
63319162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6332a717540cSStefano Zampini                 if (row != col) {
63339162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6334a717540cSStefano Zampini                 } else {
63359162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6336a717540cSStefano Zampini                 }
6337906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6338a717540cSStefano Zampini               }
6339a717540cSStefano Zampini             }
6340a717540cSStefano Zampini           }
634198a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
634222d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6343a717540cSStefano Zampini           }
6344674ae819SStefano Zampini         }
6345984c4197SStefano Zampini       } else {
6346984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
63479162d606SStefano 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);
6348674ae819SStefano Zampini         }
6349674ae819SStefano Zampini       }
6350674ae819SStefano Zampini     }
6351a717540cSStefano Zampini 
6352a717540cSStefano Zampini     /* free workspace */
6353a717540cSStefano Zampini     if (qr_needed) {
6354984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6355cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6356984c4197SStefano Zampini       }
6357984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6358984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6359984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6360984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6361984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6362674ae819SStefano Zampini     }
6363a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6364906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6365906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6366906d46d4SStefano Zampini 
6367906d46d4SStefano Zampini     /* assembling of global change of variable */
636888c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6369bbb9e6c6SStefano Zampini       Mat      tmat;
637016f15bc4SStefano Zampini       PetscInt bs;
637116f15bc4SStefano Zampini 
6372906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6373906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6374bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6375bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6376bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6377bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
637816f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
637916f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6380906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6381bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6382bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6383bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6384bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6385bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6386e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6387e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6388bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6389bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
639088c03ad3SStefano Zampini 
6391906d46d4SStefano Zampini       /* check */
6392906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6393906d46d4SStefano Zampini         PetscReal error;
6394906d46d4SStefano Zampini         Vec       x,x_change;
6395906d46d4SStefano Zampini 
6396906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6397906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6398906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6399906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6400e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6401e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6402bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6403e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6404e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6405906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6406906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6407906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6408637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6409637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6410637e8532SStefano Zampini         }
6411906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6412906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6413906d46d4SStefano Zampini       }
6414b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6415b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6416b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6417bf3a8328SStefano Zampini 
641813903a91SSatish Balay         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");
6419b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6420ac632422SStefano Zampini           Mat                    S_new,tmat;
6421bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6422bbb9e6c6SStefano Zampini 
6423bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
64247dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6425bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6426bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6427bf3a8328SStefano Zampini             IS                     is_V;
6428b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6429b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6430b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6431b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6432b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6433bf3a8328SStefano Zampini           }
6434bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6435ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6436b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6437ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6438bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6439bf3a8328SStefano Zampini             const PetscScalar *array;
6440bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6441bf3a8328SStefano Zampini             PetscInt          i,n_V;
6442bf3a8328SStefano Zampini 
6443b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6444b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6445b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6446b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6447b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6448b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6449b087196eSStefano Zampini               PetscScalar val;
6450b087196eSStefano Zampini               PetscInt    idx;
6451b087196eSStefano Zampini 
6452b087196eSStefano Zampini               idx = idxs_V[i];
6453b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6454b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6455b087196eSStefano Zampini             }
6456b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6457b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6458bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6459bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6460bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6461bf3a8328SStefano Zampini           }
6462ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6463ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6464ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6465ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6466b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6467ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6468bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6469b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6470bf3a8328SStefano Zampini             }
6471ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6472ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6473ac632422SStefano Zampini           }
6474b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
647588c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6476b96c3477SStefano Zampini         }
6477c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6478b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6479c9db6a07SStefano Zampini           PetscInt i;
6480c9db6a07SStefano Zampini 
6481c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6482c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6483c9db6a07SStefano Zampini           }
6484c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6485c9db6a07SStefano Zampini         }
6486b96c3477SStefano Zampini       }
648716909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
648816909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
648916909a7fSStefano Zampini       } else {
6490906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
649116909a7fSStefano Zampini       }
64921dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
649327b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
649472b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
649572b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
649672b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
649772b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
649872b8c272SStefano Zampini     }
64991dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
650027b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6501b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6502b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6503906d46d4SStefano Zampini     } else {
65041dd7afcfSStefano Zampini       Mat benign_global = NULL;
650527b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
65061dd7afcfSStefano Zampini         Mat tmat;
65071dd7afcfSStefano Zampini 
65081dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
65091dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
65101dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
65111dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
65121dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
65131dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
65141dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
65151dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
65161dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
65171dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
65181dd7afcfSStefano Zampini           Mat M;
65191dd7afcfSStefano Zampini 
65201dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
65211dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
65221dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
65231dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6524906d46d4SStefano Zampini         } else {
65251dd7afcfSStefano Zampini           Mat         eye;
65261dd7afcfSStefano Zampini           PetscScalar *array;
65271dd7afcfSStefano Zampini 
65281dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
65291dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
65301dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
65311dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6532906d46d4SStefano Zampini           }
65331dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
65341dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65351dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65361dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
65371dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
65381dd7afcfSStefano Zampini         }
65391dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
65401dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
65411dd7afcfSStefano Zampini       }
65421dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
65431dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
65441dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
654527b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
65461dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
65471dd7afcfSStefano Zampini       }
65481dd7afcfSStefano Zampini     }
654916909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
655016909a7fSStefano Zampini       IS             is_global;
655116909a7fSStefano Zampini       const PetscInt *gidxs;
655216909a7fSStefano Zampini 
655316909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
655416909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
655516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
65567dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
655716909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
655816909a7fSStefano Zampini     }
65591dd7afcfSStefano Zampini   }
65601dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
65611dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6562b9b85e73SStefano Zampini   }
6563a717540cSStefano Zampini 
656472b8c272SStefano Zampini   if (!pcbddc->fake_change) {
65654f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
65664f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
65674f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
65684f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6569019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6570019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6571019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6572019a44ceSStefano Zampini     }
6573019a44ceSStefano Zampini 
6574019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6575727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6576727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
65779f47a83aSStefano 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);
6578c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
65790e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
65809f47a83aSStefano 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);
6581727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6582727cdba6SStefano Zampini       }
65830e6343abSStefano Zampini     }
6584727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6585b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
658672b8c272SStefano Zampini   }
658772b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6588727cdba6SStefano Zampini 
6589a717540cSStefano Zampini   /* flush dbg viewer */
6590b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6591b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6592b8ffe317SStefano Zampini   }
6593a717540cSStefano Zampini 
6594e310c8b4SStefano Zampini   /* free workspace */
6595a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
65964641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
659708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
65989162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
65999162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
660008122e43SStefano Zampini   } else {
66019162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
66029162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
66039162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
660408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
660508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
66069162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
66079162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
660808122e43SStefano Zampini   }
6609674ae819SStefano Zampini   PetscFunctionReturn(0);
6610674ae819SStefano Zampini }
6611674ae819SStefano Zampini 
6612674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6613674ae819SStefano Zampini {
661471582508SStefano Zampini   ISLocalToGlobalMapping map;
6615674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6616674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
661766da6bd7Sstefano_zampini   PetscInt               i,N;
661866da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
661966da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6620674ae819SStefano Zampini 
6621674ae819SStefano Zampini   PetscFunctionBegin;
66228af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6623b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
66248e61c736SStefano Zampini     /* Reset previously computed graph */
66258e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6626674ae819SStefano Zampini     /* Init local Graph struct */
66277fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
662871582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6629be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6630674ae819SStefano Zampini 
66317a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
66327a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
66337a0e7b2cSstefano_zampini     }
6634575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
66359a962809SStefano 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);
66369577ea80SStefano Zampini 
6637674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
663866da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
66394d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
66404d379d7bSStefano Zampini       PetscInt  nvtxs;
6641e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6642674ae819SStefano Zampini 
66432fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
66442fffb893SStefano Zampini       if (flg_row) {
66454d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6646b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
66472fffb893SStefano Zampini       }
66482fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
664966da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6650674ae819SStefano Zampini     }
66519b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
66529b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6653674ae819SStefano Zampini     }
6654674ae819SStefano Zampini 
6655674ae819SStefano Zampini     /* Setup of Graph */
66564b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
665714f95afaSStefano 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);
6658674ae819SStefano Zampini 
66594f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
66604f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
66614f1b2e48SStefano Zampini       PetscInt *local_subs;
66624f1b2e48SStefano Zampini 
66634f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
66644f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
66654f1b2e48SStefano Zampini         const PetscInt *idxs;
66664f1b2e48SStefano Zampini         PetscInt       nl,j;
66674f1b2e48SStefano Zampini 
66684f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
66694f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
667071582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
66714f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
66724f1b2e48SStefano Zampini       }
66734f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
66744f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
66754f1b2e48SStefano Zampini     }
66768af8fcf9SStefano Zampini   }
66774f1b2e48SStefano Zampini 
6678cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6679674ae819SStefano Zampini     /* Graph's connected components analysis */
6680674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
668171582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
66828af8fcf9SStefano Zampini   }
668366da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6684674ae819SStefano Zampini   PetscFunctionReturn(0);
6685674ae819SStefano Zampini }
6686674ae819SStefano Zampini 
66879a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
66889a7d3425SStefano Zampini {
66899a7d3425SStefano Zampini   PetscInt       i,j;
66909a7d3425SStefano Zampini   PetscScalar    *alphas;
66919a7d3425SStefano Zampini   PetscErrorCode ierr;
66929a7d3425SStefano Zampini 
66939a7d3425SStefano Zampini   PetscFunctionBegin;
6694785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
66959a7d3425SStefano Zampini   for (i=0;i<n;i++) {
66969a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6697669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6698669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6699669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
67009a7d3425SStefano Zampini   }
67019a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
67029a7d3425SStefano Zampini   PetscFunctionReturn(0);
67039a7d3425SStefano Zampini }
67049a7d3425SStefano Zampini 
6705bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6706e7931f94SStefano Zampini {
670757de7509SStefano Zampini   Mat            A;
6708e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6709e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
671052e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
671152e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6712bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
671357de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
671427b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
671527b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
671627b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
671727b6a85dSStefano Zampini   MPI_Comm       subcomm;
671852e5ac9dSStefano Zampini   PetscErrorCode ierr;
6719a57a6d2fSStefano Zampini 
6720e7931f94SStefano Zampini   PetscFunctionBegin;
672157de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
672257de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6723fbfcfee5SBarry 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);
672457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
672557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
672657de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
672757de7509SStefano Zampini 
672857de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
672957de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
673057de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
673157de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
673257de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6733bb360cb4SStefano Zampini   im_active = !!n;
673457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
673557de7509SStefano Zampini   void_procs = size - active_procs;
673657de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
673757de7509SStefano Zampini   if (void_procs) {
673857de7509SStefano Zampini     PetscInt ncand;
673957de7509SStefano Zampini 
674057de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
674157de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
674257de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
674357de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
674457de7509SStefano Zampini       if (!procs_candidates[i]) {
674557de7509SStefano Zampini         procs_candidates[ncand++] = i;
674657de7509SStefano Zampini       }
674757de7509SStefano Zampini     }
674857de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
674957de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
675057de7509SStefano Zampini   }
675157de7509SStefano Zampini 
6752bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
675314f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
6754bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
6755bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
675614f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
675714f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
675814f0bfb9SStefano Zampini     else dest = rank;
675957de7509SStefano Zampini     if (im_active) {
676057de7509SStefano Zampini       issize = 1;
676157de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
676214f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
676357de7509SStefano Zampini       } else {
676414f0bfb9SStefano Zampini         isidx = dest;
676557de7509SStefano Zampini       }
676657de7509SStefano Zampini     } else {
676757de7509SStefano Zampini       issize = 0;
676857de7509SStefano Zampini       isidx = -1;
676957de7509SStefano Zampini     }
6770bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
677157de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6772daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
677357de7509SStefano Zampini     PetscFunctionReturn(0);
677457de7509SStefano Zampini   }
6775c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6776c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
677727b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6778e7931f94SStefano Zampini 
6779e7931f94SStefano Zampini   /* Get info on mapping */
67803bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6781e7931f94SStefano Zampini 
6782e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6783785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6784e7931f94SStefano Zampini   xadj[0] = 0;
6785e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6786785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6787785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
6788bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
678927b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
679027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
679127b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6792e7931f94SStefano Zampini 
679327b6a85dSStefano Zampini   xadj_count = 0;
67942b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
679527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
679627b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6797d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6798d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6799d023bfaeSStefano Zampini         xadj_count++;
680027b6a85dSStefano Zampini         break;
680127b6a85dSStefano Zampini       }
6802e7931f94SStefano Zampini     }
6803e7931f94SStefano Zampini   }
6804d023bfaeSStefano Zampini   xadj[1] = xadj_count;
680527b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
68063bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6807e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6808e7931f94SStefano Zampini 
68093837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6810e7931f94SStefano Zampini 
681127b6a85dSStefano Zampini   /* Restrict work on active processes only */
681227b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
681327b6a85dSStefano Zampini   if (void_procs) {
681427b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
681527b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
681627b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
681727b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
681827b6a85dSStefano Zampini   } else {
681927b6a85dSStefano Zampini     psubcomm = NULL;
682027b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
682127b6a85dSStefano Zampini   }
682227b6a85dSStefano Zampini 
682327b6a85dSStefano Zampini   v_wgt = NULL;
682427b6a85dSStefano Zampini   if (!color) {
6825e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6826e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6827e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6828c8587f34SStefano Zampini   } else {
682952e5ac9dSStefano Zampini     Mat             subdomain_adj;
683052e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
683152e5ac9dSStefano Zampini     MatPartitioning partitioner;
683227b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
683352e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
683457de7509SStefano Zampini     PetscMPIInt     size;
6835b0c7d250SStefano Zampini     PetscBool       aggregate;
6836b0c7d250SStefano Zampini 
683727b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
683827b6a85dSStefano Zampini     if (void_procs) {
683927b6a85dSStefano Zampini       PetscInt prank = rank;
6840785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
684127b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6842e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6843e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6844c8587f34SStefano Zampini       }
6845e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
684627b6a85dSStefano Zampini     } else {
684727b6a85dSStefano Zampini       oldranks = NULL;
684827b6a85dSStefano Zampini     }
6849b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
685027b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6851b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6852b0c7d250SStefano Zampini       PetscMPIInt nrank;
6853b0c7d250SStefano Zampini       PetscScalar *vals;
6854b0c7d250SStefano Zampini 
685527b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6856b0c7d250SStefano Zampini       lrows = 0;
6857b0c7d250SStefano Zampini       if (nrank<redprocs) {
6858b0c7d250SStefano Zampini         lrows = size/redprocs;
6859b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6860b0c7d250SStefano Zampini       }
686127b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6862b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6863b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6864b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6865b0c7d250SStefano Zampini       row = nrank;
6866b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6867b0c7d250SStefano Zampini       cols = adjncy;
6868b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6869b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6870b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6871b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6872b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
687352e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
687452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
687552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6876b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
687727b6a85dSStefano Zampini       if (use_vwgt) {
687827b6a85dSStefano Zampini         Vec               v;
687927b6a85dSStefano Zampini         const PetscScalar *array;
688027b6a85dSStefano Zampini         PetscInt          nl;
688127b6a85dSStefano Zampini 
688227b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
6883bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
688427b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
688527b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
688627b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
688727b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
688827b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
688922db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
689027b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
689127b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
689227b6a85dSStefano Zampini       }
6893b0c7d250SStefano Zampini     } else {
689427b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
689527b6a85dSStefano Zampini       if (use_vwgt) {
689627b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
6897bb360cb4SStefano Zampini         v_wgt[0] = n;
689827b6a85dSStefano Zampini       }
6899b0c7d250SStefano Zampini     }
690022b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6901e7931f94SStefano Zampini 
6902e7931f94SStefano Zampini     /* Partition */
690327b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6904e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
690527b6a85dSStefano Zampini     if (v_wgt) {
6906e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6907c8587f34SStefano Zampini     }
690857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
690957de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6910e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6911e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
691222b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6913e7931f94SStefano Zampini 
691452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
69156583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
691652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
691752e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
691857de7509SStefano Zampini     if (!aggregate) {
691957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
692027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
692127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
692227b6a85dSStefano Zampini #endif
692357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
692427b6a85dSStefano Zampini       } else if (oldranks) {
6925b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
692627b6a85dSStefano Zampini       } else {
692727b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
692857de7509SStefano Zampini       }
692928143c3dSStefano Zampini     } else {
69307fb8a5e4SKarl Rupp       PetscInt    idx = 0;
6931b0c7d250SStefano Zampini       PetscMPIInt tag;
6932b0c7d250SStefano Zampini       MPI_Request *reqs;
6933b0c7d250SStefano Zampini 
6934b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6935b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6936b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
693727b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
693828143c3dSStefano Zampini       }
69397fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6940b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6941b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
694257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
694327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
694427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
694527b6a85dSStefano Zampini #endif
69467fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
694727b6a85dSStefano Zampini       } else if (oldranks) {
69487fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
694927b6a85dSStefano Zampini       } else {
69507fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
6951e7931f94SStefano Zampini       }
695257de7509SStefano Zampini     }
695352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6954e7931f94SStefano Zampini     /* clean up */
6955e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
695652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6957e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6958e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6959e7931f94SStefano Zampini   }
696027b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
696157de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6962e7931f94SStefano Zampini 
6963e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6964e7931f94SStefano Zampini   i = 1;
696527b6a85dSStefano Zampini   if (!color) i=0;
696657de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6967e7931f94SStefano Zampini   PetscFunctionReturn(0);
6968e7931f94SStefano Zampini }
6969e7931f94SStefano Zampini 
6970e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6971e7931f94SStefano Zampini 
69721e0482f5SStefano 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[])
6973e7931f94SStefano Zampini {
697470cf5478SStefano Zampini   Mat                    local_mat;
6975e7931f94SStefano Zampini   IS                     is_sends_internal;
69769d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
69771ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
69789d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6979e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6980e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6981e7931f94SStefano Zampini   const PetscInt*        is_indices;
6982e7931f94SStefano Zampini   MatType                new_local_type;
6983e7931f94SStefano Zampini   /* buffers */
6984e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
698528143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
69869d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6987e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
69881ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6989e7931f94SStefano Zampini   /* MPI */
699028143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
699128143c3dSStefano Zampini   PetscSubcomm           subcomm;
6992e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
699328143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
699428143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
69951ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
69961ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
69971ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6998e7931f94SStefano Zampini   PetscErrorCode         ierr;
6999e7931f94SStefano Zampini 
7000e7931f94SStefano Zampini   PetscFunctionBegin;
700157de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7002e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7003fbfcfee5SBarry 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);
700457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
700557de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
700657de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
700757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
700857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
70091ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
70101ae86dd6SStefano Zampini   if (nvecs) {
70111ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
70121ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
70131ae86dd6SStefano Zampini   }
701457de7509SStefano Zampini   /* further checks */
7015e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7016e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7017e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7018e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7019e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
702057de7509SStefano Zampini   if (reuse && *mat_n) {
702170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
702257de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
702370cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
702428143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
702570cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
702670cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
702770cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
702870cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
702970cf5478SStefano Zampini   }
7030e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7031e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
703257de7509SStefano Zampini 
7033e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7034e7931f94SStefano Zampini   if (!is_sends) {
703528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7036bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7037c8587f34SStefano Zampini   } else {
7038e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7039e7931f94SStefano Zampini     is_sends_internal = is_sends;
7040c8587f34SStefano Zampini   }
7041e7931f94SStefano Zampini 
7042e7931f94SStefano Zampini   /* get comm */
7043a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7044e7931f94SStefano Zampini 
7045e7931f94SStefano Zampini   /* compute number of sends */
7046e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7047e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7048e7931f94SStefano Zampini 
7049e7931f94SStefano Zampini   /* compute number of receives */
7050e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
7051785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
7052e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
7053e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7054e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7055e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7056e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7057e7931f94SStefano Zampini 
705828143c3dSStefano Zampini   /* restrict comm if requested */
705928143c3dSStefano Zampini   subcomm = 0;
706028143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
706128143c3dSStefano Zampini   if (restrict_comm) {
7062779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7063779c1cceSStefano Zampini 
706428143c3dSStefano Zampini     color = 0;
706553a05cb3SStefano Zampini     if (restrict_full) {
706653a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
706753a05cb3SStefano Zampini     } else {
706853a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
706953a05cb3SStefano Zampini     }
7070b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
707128143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
707228143c3dSStefano Zampini     /* check if reuse has been requested */
707357de7509SStefano Zampini     if (reuse) {
707428143c3dSStefano Zampini       if (*mat_n) {
707528143c3dSStefano Zampini         PetscMPIInt subcommsize2;
707628143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
707728143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
707828143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
707928143c3dSStefano Zampini       } else {
708028143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
708128143c3dSStefano Zampini       }
708228143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7083779c1cceSStefano Zampini       PetscMPIInt rank;
7084779c1cceSStefano Zampini 
7085779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
708628143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
708728143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
708828143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7089306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
709028143c3dSStefano Zampini     }
709128143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
709228143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
709328143c3dSStefano Zampini   } else {
709428143c3dSStefano Zampini     comm_n = comm;
709528143c3dSStefano Zampini   }
709628143c3dSStefano Zampini 
7097e7931f94SStefano Zampini   /* prepare send/receive buffers */
7098785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
7099e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7100785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
7101e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
710228143c3dSStefano Zampini   if (nis) {
7103854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
710428143c3dSStefano Zampini   }
7105e7931f94SStefano Zampini 
710628143c3dSStefano Zampini   /* Get data from local matrices */
71076c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7108e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7109e7931f94SStefano Zampini     /*
7110e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7111e7931f94SStefano Zampini        send_buffer_idxs should contain:
7112e7931f94SStefano Zampini        - MatType_PRIVATE type
7113e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7114e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7115e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7116e7931f94SStefano Zampini     */
71176c4ed002SBarry Smith   else {
7118e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
71193bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7120854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7121e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7122e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
71233bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7124e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
71253bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7126e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7127e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7128e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7129e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7130c8587f34SStefano Zampini     }
7131c8587f34SStefano Zampini   }
7132e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
713328143c3dSStefano Zampini   /* additional is (if any) */
713428143c3dSStefano Zampini   if (nis) {
713528143c3dSStefano Zampini     PetscMPIInt psum;
713628143c3dSStefano Zampini     PetscInt j;
713728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
713828143c3dSStefano Zampini       PetscInt plen;
713928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
714028143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
714128143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
714228143c3dSStefano Zampini     }
7143854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
714428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
714528143c3dSStefano Zampini       PetscInt plen;
714628143c3dSStefano Zampini       const PetscInt *is_array_idxs;
714728143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
714828143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
714928143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
715028143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
715128143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
715228143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
715328143c3dSStefano Zampini     }
715428143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
715528143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
715628143c3dSStefano Zampini     }
715728143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
715828143c3dSStefano Zampini   }
71593b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
716028143c3dSStefano Zampini 
7161e7931f94SStefano Zampini   buf_size_idxs = 0;
7162e7931f94SStefano Zampini   buf_size_vals = 0;
716328143c3dSStefano Zampini   buf_size_idxs_is = 0;
71641ae86dd6SStefano Zampini   buf_size_vecs = 0;
7165e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7166e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7167e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
716828143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
71691ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7170e7931f94SStefano Zampini   }
7171785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7172785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
717395ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
71741ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7175e7931f94SStefano Zampini 
7176e7931f94SStefano Zampini   /* get new tags for clean communications */
7177e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7178e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
717928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
71801ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7181e7931f94SStefano Zampini 
7182e7931f94SStefano Zampini   /* allocate for requests */
7183785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7184785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
718595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
71861ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7187785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7188785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
718995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
71901ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7191e7931f94SStefano Zampini 
7192e7931f94SStefano Zampini   /* communications */
7193e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7194e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
719528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
71961ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7197e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7198e7931f94SStefano Zampini     source_dest = onodes[i];
7199e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7200e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7201e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7202e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
720328143c3dSStefano Zampini     if (nis) {
720457de7509SStefano Zampini       source_dest = onodes_is[i];
720528143c3dSStefano 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);
720628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
720728143c3dSStefano Zampini     }
72081ae86dd6SStefano Zampini     if (nvecs) {
72091ae86dd6SStefano Zampini       source_dest = onodes[i];
72101ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
72111ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
72121ae86dd6SStefano Zampini     }
7213e7931f94SStefano Zampini   }
7214e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7215e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7216e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7217e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
721828143c3dSStefano Zampini     if (nis) {
721928143c3dSStefano 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);
722028143c3dSStefano Zampini     }
72211ae86dd6SStefano Zampini     if (nvecs) {
72221ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
72231ae86dd6SStefano 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);
72241ae86dd6SStefano Zampini     }
7225e7931f94SStefano Zampini   }
7226e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7227e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7228e7931f94SStefano Zampini 
7229e7931f94SStefano Zampini   /* assemble new l2g map */
7230e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7231e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
72329d30be91SStefano Zampini   new_local_rows = 0;
7233e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
72349d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7235e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7236e7931f94SStefano Zampini   }
72379d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7238e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
72399d30be91SStefano Zampini   new_local_rows = 0;
7240e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
72419d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
72429d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7243e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7244e7931f94SStefano Zampini   }
72459d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
72469d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7247e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7248e7931f94SStefano Zampini 
7249e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7250e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7251e7931f94SStefano 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) */
7252e7931f94SStefano Zampini   if (n_recvs) {
725328143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7254e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7255e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7256e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7257e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7258e7931f94SStefano Zampini         break;
7259e7931f94SStefano Zampini       }
7260e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7261e7931f94SStefano Zampini     }
7262e7931f94SStefano Zampini     switch (new_local_type_private) {
726328143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7264e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7265e7931f94SStefano Zampini         bs = 1;
7266e7931f94SStefano Zampini         break;
7267e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7268e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7269e7931f94SStefano Zampini         bs = 1;
7270e7931f94SStefano Zampini         break;
7271e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7272e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7273e7931f94SStefano Zampini         break;
7274e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7275e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7276e7931f94SStefano Zampini         break;
7277e7931f94SStefano Zampini       default:
7278fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7279e7931f94SStefano Zampini         break;
7280e7931f94SStefano Zampini     }
7281ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7282ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
728328143c3dSStefano Zampini     bs = 1;
7284e7931f94SStefano Zampini   }
7285e7931f94SStefano Zampini 
728670cf5478SStefano Zampini   /* create MATIS object if needed */
728757de7509SStefano Zampini   if (!reuse) {
7288e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7289e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
729070cf5478SStefano Zampini   } else {
729170cf5478SStefano Zampini     /* it also destroys the local matrices */
729257de7509SStefano Zampini     if (*mat_n) {
729370cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
729457de7509SStefano Zampini     } else { /* this is a fake object */
729557de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
729657de7509SStefano Zampini     }
729770cf5478SStefano Zampini   }
729870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7299e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
73009d30be91SStefano Zampini 
73019d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
73029d30be91SStefano Zampini 
73039d30be91SStefano Zampini   /* Global to local map of received indices */
73049d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
73059d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
73069d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
73079d30be91SStefano Zampini 
73089d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
73099d30be91SStefano Zampini   buf_size_idxs = 0;
73109d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
73119d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
73129d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
73139d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
73149d30be91SStefano Zampini   }
73159d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
73169d30be91SStefano Zampini 
73179d30be91SStefano Zampini   /* set preallocation */
73189d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
73199d30be91SStefano Zampini   if (!newisdense) {
73209d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
73219d30be91SStefano Zampini 
73229d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
73239d30be91SStefano Zampini     if (n_recvs) {
73249d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
73259d30be91SStefano Zampini     }
73269d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
73279d30be91SStefano Zampini       PetscInt j;
73289d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
73299d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
73309d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
73319d30be91SStefano Zampini         }
73329d30be91SStefano Zampini       } else {
73339d30be91SStefano Zampini         /* TODO */
73349d30be91SStefano Zampini       }
73359d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
73369d30be91SStefano Zampini     }
73379d30be91SStefano Zampini     if (new_local_nnz) {
73389d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
73399d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
73409d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
73419d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
73429d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
73439d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
73449d30be91SStefano Zampini     } else {
73459d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
73469d30be91SStefano Zampini     }
73479d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
73489d30be91SStefano Zampini   } else {
73499d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
73509d30be91SStefano Zampini   }
7351e7931f94SStefano Zampini 
7352e7931f94SStefano Zampini   /* set values */
7353e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
73549d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7355e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7356e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7357e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
73589d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7359e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7360e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7361e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
736228143c3dSStefano Zampini     } else {
736328143c3dSStefano Zampini       /* TODO */
7364e7931f94SStefano Zampini     }
7365e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7366e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7367e7931f94SStefano Zampini   }
7368e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7369e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
73703b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
737170cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
737270cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
73739d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7374e7931f94SStefano Zampini 
7375dfd14d43SStefano Zampini #if 0
737628143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7377e7931f94SStefano Zampini     Vec       lvec,rvec;
7378e7931f94SStefano Zampini     PetscReal infty_error;
7379e7931f94SStefano Zampini 
73802a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7381e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7382e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7383e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
738470cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7385e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7386e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7387e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7388e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7389e7931f94SStefano Zampini   }
739028143c3dSStefano Zampini #endif
7391e7931f94SStefano Zampini 
739228143c3dSStefano Zampini   /* assemble new additional is (if any) */
739328143c3dSStefano Zampini   if (nis) {
739428143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
739528143c3dSStefano Zampini 
739628143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7397854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
739828143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
739928143c3dSStefano Zampini     psum = 0;
740028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
740128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
740228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
740328143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
740428143c3dSStefano Zampini         psum += plen;
740528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
740628143c3dSStefano Zampini       }
740728143c3dSStefano Zampini     }
7408854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7409854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
741028143c3dSStefano Zampini     for (i=1;i<nis;i++) {
741128143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
741228143c3dSStefano Zampini     }
741328143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
741428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
741528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
741628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
741728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
741828143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
741928143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
742028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
742128143c3dSStefano Zampini       }
742228143c3dSStefano Zampini     }
742328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
742428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
742528143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
742628143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
742728143c3dSStefano Zampini     }
742828143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
742928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
743028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
743128143c3dSStefano Zampini   }
7432e7931f94SStefano Zampini   /* free workspace */
743328143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7434e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7435e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7436e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7437e7931f94SStefano Zampini   if (isdense) {
7438e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7439e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
74403b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7441e7931f94SStefano Zampini   } else {
7442e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7443e7931f94SStefano Zampini   }
744428143c3dSStefano Zampini   if (nis) {
744528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
744628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
744728143c3dSStefano Zampini   }
74481ae86dd6SStefano Zampini 
74491ae86dd6SStefano Zampini   if (nvecs) {
74501ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
74511ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
74521ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74531ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
74541ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
74551ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
74561ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
74571ae86dd6SStefano Zampini     /* set values */
74581ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
74591ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
74601ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74611ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
74621ae86dd6SStefano Zampini       PetscInt j;
74631ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
74641ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
74651ae86dd6SStefano Zampini       }
74661ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
74671ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
74681ae86dd6SStefano Zampini     }
74691ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74701ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
74711ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
74721ae86dd6SStefano Zampini   }
74731ae86dd6SStefano Zampini 
74741ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
74751ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7476e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7477e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
74781ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
747928143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7480e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7481e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
74821ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
748328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7484e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7485e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7486e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7487e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7488e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
748928143c3dSStefano Zampini   if (nis) {
749028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
749128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
749228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
749328143c3dSStefano Zampini   }
749428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
749528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
749628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
749728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
749828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
749928143c3dSStefano Zampini     }
75001ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
75011ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
75021ae86dd6SStefano Zampini     }
750353a05cb3SStefano Zampini     *mat_n = NULL;
750428143c3dSStefano Zampini   }
7505e7931f94SStefano Zampini   PetscFunctionReturn(0);
7506e7931f94SStefano Zampini }
7507a57a6d2fSStefano Zampini 
750812edc857SStefano Zampini /* temporary hack into ksp private data structure */
7509af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
751012edc857SStefano Zampini 
7511c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7512c8587f34SStefano Zampini {
7513c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7514c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
751520a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
75161ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
75171e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
75189881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
751920a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
75206e683305SStefano Zampini   IS                     coarse_is,*isarray;
75216e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
752230368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7523f9eb5b7dSStefano Zampini   PC                     pc_temp;
7524c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7525c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7526f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
75277274672aSStefano Zampini   PetscBool              coarse_reuse;
75281e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
752968457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
753022bc73bbSStefano Zampini   PetscScalar            *array;
753157de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
753257de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
75337de4f681Sstefano_zampini   PetscMPIInt            commsize;
75349881197aSStefano Zampini   PetscErrorCode         ierr;
7535fdc09c96SStefano Zampini 
7536c8587f34SStefano Zampini   PetscFunctionBegin;
7537c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
753868457ee5SStefano 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 */
7539fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
75405a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
75417de4f681Sstefano_zampini 
75427de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7543fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7544f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7545f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7546f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7547fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
754851bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
754951bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7550727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7551fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7552fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7553fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7554f4ddd8eeSStefano Zampini       }
7555fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7556fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7557f4ddd8eeSStefano Zampini     }
755870cf5478SStefano Zampini     /* reset any subassembling information */
755957de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
756070cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
756157de7509SStefano Zampini     }
75626e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7563fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7564f4ddd8eeSStefano Zampini   }
756557de7509SStefano Zampini   /* assemble coarse matrix */
756657de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
756757de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
756857de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
756957de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
757018a45a71SStefano Zampini   } else {
757157de7509SStefano Zampini     coarse_mat = NULL;
757257de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
75736e683305SStefano Zampini   }
7574e7931f94SStefano Zampini 
7575abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7576abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7577abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7578abbbba34SStefano Zampini 
7579abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
758022bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
758122bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
758222bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
758322bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7584e176bc59SStefano 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);
75856e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
75866e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
75876e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7588abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7589abbbba34SStefano Zampini 
759057de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
759157de7509SStefano Zampini   im_active = !!(pcis->n);
759257de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
759357de7509SStefano Zampini 
759414f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
759557de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
759657de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
75977de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
759857de7509SStefano Zampini   coarse_mat_is = NULL;
759957de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
760057de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
76011ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
760257de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
760357de7509SStefano Zampini   if (multilevel_requested) {
760457de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
760557de7509SStefano Zampini     restr = PETSC_FALSE;
760657de7509SStefano Zampini     full_restr = PETSC_FALSE;
760757de7509SStefano Zampini   } else {
760857de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
760957de7509SStefano Zampini     restr = PETSC_TRUE;
761057de7509SStefano Zampini     full_restr = PETSC_TRUE;
761157de7509SStefano Zampini   }
76127de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
761357de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
761457de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7615a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7616bb360cb4SStefano Zampini       if (multilevel_requested) {
7617bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7618bb360cb4SStefano Zampini       } else {
7619bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7620bb360cb4SStefano Zampini       }
7621a198735bSStefano Zampini     } else {
76227de4f681Sstefano_zampini       PetscMPIInt rank;
7623a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
76247de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7625a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7626a198735bSStefano Zampini     }
762757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
762857de7509SStefano Zampini     PetscInt    psum;
762957de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
763057de7509SStefano Zampini     else psum = 0;
763157de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
76327de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
763357de7509SStefano Zampini   }
763457de7509SStefano Zampini   /* determine if we can go multilevel */
763557de7509SStefano Zampini   if (multilevel_requested) {
763657de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
763757de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
763857de7509SStefano Zampini   }
763957de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
764057de7509SStefano Zampini 
7641e4d548c7SStefano Zampini   /* dump subassembling pattern */
7642e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7643e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7644e4d548c7SStefano Zampini   }
7645e4d548c7SStefano Zampini 
76466e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
76471e0482f5SStefano Zampini   nedcfield = -1;
76481e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
76496e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
76506e683305SStefano Zampini     const PetscInt         *idxs;
76516e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
76526e683305SStefano Zampini 
76536e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
76540be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
76556e683305SStefano Zampini     /* allocate space for temporary storage */
7656854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7657854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
76586e683305SStefano Zampini     /* allocate for IS array */
76596e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
76601e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
76611e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
76621e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
76631e0482f5SStefano Zampini       } else {
76641e0482f5SStefano Zampini         nedcfield = 0;
76651e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
76661e0482f5SStefano Zampini         nisdofs = 1;
76671e0482f5SStefano Zampini       }
76681e0482f5SStefano Zampini     }
76696e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
767027b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
767130368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7672854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
76736e683305SStefano Zampini     /* dofs splitting */
76746e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
76756e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
76761e0482f5SStefano Zampini       if (nedcfield != i) {
76776e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
76786e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
76796e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
76806e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
76811e0482f5SStefano Zampini       } else {
76821e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
76831e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
76841e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7685eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
76861e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
76871e0482f5SStefano Zampini       }
76886e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
768930368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
76906e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
76916e683305SStefano Zampini     }
76926e683305SStefano Zampini     /* neumann boundaries */
76936e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
76946e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
76956e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
76966e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
76976e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
76986e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
76996e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
770030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
77016e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
77026e683305SStefano Zampini     }
77036e683305SStefano Zampini     /* free memory */
77046e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
77056e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
77066e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
77076e683305SStefano Zampini   } else {
77086e683305SStefano Zampini     nis = 0;
77096e683305SStefano Zampini     nisdofs = 0;
77106e683305SStefano Zampini     nisneu = 0;
771130368db7SStefano Zampini     nisvert = 0;
77126e683305SStefano Zampini     isarray = NULL;
77136e683305SStefano Zampini   }
77146e683305SStefano Zampini   /* destroy no longer needed map */
77156e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
77166e683305SStefano Zampini 
771757de7509SStefano Zampini   /* subassemble */
771857de7509SStefano Zampini   if (multilevel_allowed) {
77191ae86dd6SStefano Zampini     Vec       vp[1];
77201ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
772157de7509SStefano Zampini     PetscBool reuse,reuser;
77221ae86dd6SStefano Zampini 
772357de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
772457de7509SStefano Zampini     else reuse = PETSC_FALSE;
772557de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
77261ae86dd6SStefano Zampini     vp[0] = NULL;
77271ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
77281ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
77291ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
77301ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
77311ae86dd6SStefano Zampini       nvecs = 1;
77321ae86dd6SStefano Zampini 
77331ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7734a198735bSStefano Zampini         Mat      B,loc_divudotp;
77351ae86dd6SStefano Zampini         Vec      v,p;
77361ae86dd6SStefano Zampini         IS       dummy;
77371ae86dd6SStefano Zampini         PetscInt np;
77381ae86dd6SStefano Zampini 
7739a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7740a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
77411ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
77427dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
77431ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
77441ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
77451ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
77461ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
77471ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
77481ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
77491ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
77501ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
77511ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
77521ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
77531ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
77541ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
775574e2c79eSStefano Zampini       }
77561ae86dd6SStefano Zampini     }
77571ae86dd6SStefano Zampini     if (reuser) {
77581e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
775974e2c79eSStefano Zampini     } else {
77601e0482f5SStefano 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);
77611ae86dd6SStefano Zampini     }
77621ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
77631ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
77641ae86dd6SStefano Zampini       PetscInt    nl;
77651ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
77661ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
77671ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
77681ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
77691ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
77701ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
77711ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
77721ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7773a198735bSStefano Zampini     } else {
7774a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
77751ae86dd6SStefano Zampini     }
77761ae86dd6SStefano Zampini   } else {
77771e0482f5SStefano 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);
77786e683305SStefano Zampini   }
777957de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
778057de7509SStefano Zampini     PetscMPIInt size;
7781f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
778257de7509SStefano Zampini     if (!multilevel_allowed) {
778357de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
77846e683305SStefano Zampini     } else {
778557de7509SStefano Zampini       Mat A;
7786779c1cceSStefano Zampini 
778757de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
778857de7509SStefano Zampini       if (coarse_mat_is) {
778957de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
779057de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
779157de7509SStefano Zampini         coarse_mat = coarse_mat_is;
779257de7509SStefano Zampini       }
779357de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
779457de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
779557de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7796779c1cceSStefano Zampini     }
7797779c1cceSStefano Zampini   }
779857de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
779957de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
78006e683305SStefano Zampini 
78016e683305SStefano Zampini   /* create local to global scatters for coarse problem */
780268457ee5SStefano Zampini   if (compute_vecs) {
78036e683305SStefano Zampini     PetscInt lrows;
78046e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
780557de7509SStefano Zampini     if (coarse_mat) {
780657de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
78076e683305SStefano Zampini     } else {
78086e683305SStefano Zampini       lrows = 0;
78096e683305SStefano Zampini     }
78106e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
78116e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
78126e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
78136e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
78146e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
78156e683305SStefano Zampini   }
78166e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7817c8587f34SStefano Zampini 
7818f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7819f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7820f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7821f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7822f9eb5b7dSStefano Zampini   } else {
7823f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7824f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7825c8587f34SStefano Zampini   }
7826c8587f34SStefano Zampini 
78276e683305SStefano Zampini   /* print some info if requested */
78286e683305SStefano Zampini   if (pcbddc->dbg_flag) {
78296e683305SStefano Zampini     if (!multilevel_allowed) {
78306e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
78316e683305SStefano Zampini       if (multilevel_requested) {
78326e683305SStefano 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);
78336e683305SStefano Zampini       } else if (pcbddc->max_levels) {
78346e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
78356e683305SStefano Zampini       }
78366e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
78376e683305SStefano Zampini     }
78386e683305SStefano Zampini   }
78396e683305SStefano Zampini 
78401e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
78411e0482f5SStefano Zampini   coarseG = NULL;
78421e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
78431e0482f5SStefano Zampini     MPI_Comm ccomm;
78441e0482f5SStefano Zampini     if (coarse_mat) {
78451e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
78461e0482f5SStefano Zampini     } else {
78471e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
78481e0482f5SStefano Zampini     }
78491e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
78501e0482f5SStefano Zampini   }
78511e0482f5SStefano Zampini 
7852f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
785357de7509SStefano Zampini   if (coarse_mat) {
78547274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
78556a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
78567274672aSStefano Zampini 
78576e683305SStefano Zampini     if (pcbddc->dbg_flag) {
785857de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
78596e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
78606e683305SStefano Zampini     }
7861f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7862312be037SStefano Zampini       char prefix[256],str_level[16];
7863e604994aSStefano Zampini       size_t len;
78641e0482f5SStefano Zampini 
786557de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7866422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7867c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7868f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
786957de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7870c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
78716e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7872c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
78731e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
7874c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7875e604994aSStefano Zampini       /* prefix */
7876e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7877e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7878e604994aSStefano Zampini       if (!pcbddc->current_level) {
7879e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7880e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7881c8587f34SStefano Zampini       } else {
7882e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7883312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7884312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
788534d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
788635529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
7887e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7888e604994aSStefano Zampini       }
7889e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
78903e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
78913e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
78923e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
78933e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7894f9eb5b7dSStefano Zampini       /* allow user customization */
7895f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
78963e3c6dadSStefano Zampini     }
78973e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
789851bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
78993e3c6dadSStefano Zampini     if (nisdofs) {
79003e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
79013e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
79023e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
79033e3c6dadSStefano Zampini       }
79043e3c6dadSStefano Zampini     }
79053e3c6dadSStefano Zampini     if (nisneu) {
79063e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
79073e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7908312be037SStefano Zampini     }
790930368db7SStefano Zampini     if (nisvert) {
791030368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
791130368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
791230368db7SStefano Zampini     }
79131e0482f5SStefano Zampini     if (coarseG) {
79141e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
79151e0482f5SStefano Zampini     }
7916f9eb5b7dSStefano Zampini 
7917f9eb5b7dSStefano Zampini     /* get some info after set from options */
7918f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
7919b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
7920b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
7921f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7922f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7923f9eb5b7dSStefano Zampini     }
7924b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
79257274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
79267274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
7927b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
7928b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
7929b76f3995Sstefano_zampini     }
79307274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
79314f3a063dSStefano Zampini     if (isredundant) {
79324f3a063dSStefano Zampini       KSP inner_ksp;
79334f3a063dSStefano Zampini       PC  inner_pc;
79349326c5c6Sstefano_zampini 
79354f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
79364f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
79374f3a063dSStefano Zampini     }
7938f9eb5b7dSStefano Zampini 
793957de7509SStefano Zampini     /* parameters which miss an API */
79407274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
794157de7509SStefano Zampini     if (isbddc) {
7942720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
79437274672aSStefano Zampini 
7944720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
794557de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
794627b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
794727b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7948a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7949a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7950a198735bSStefano Zampini         IS                     row,col;
7951a198735bSStefano Zampini         const PetscInt         *gidxs;
7952a198735bSStefano Zampini         PetscInt               n,st,M,N;
7953a198735bSStefano Zampini 
7954a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7955a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7956a198735bSStefano Zampini         st   = st-n;
7957a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7958a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7959a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7960a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7961a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7962a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7963a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7964a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7965a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7966a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7967a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7968a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7969a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7970a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7971a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7972a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7973a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7974a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7975a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7976a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
79778ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7978a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7979720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
798059e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7981720d30f9SStefano Zampini       }
7982d4d8cf7bSStefano Zampini     }
79839881197aSStefano Zampini 
79843301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
79855a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
79863301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
79873301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
79883301b35fSStefano Zampini     }
79893301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
79903301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
79913301b35fSStefano Zampini     }
79923301b35fSStefano Zampini     if (pc->pmat->spd_set) {
79933301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
79943301b35fSStefano Zampini     }
799527b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
799627b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
799727b6a85dSStefano Zampini     }
79986e683305SStefano Zampini     /* set operators */
79995f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
80006e683305SStefano Zampini     if (pcbddc->dbg_flag) {
80016e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
80026e683305SStefano Zampini     }
80036e683305SStefano Zampini   }
80041e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
80056e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8006b1ecc7b1SStefano Zampini #if 0
8007b9b85e73SStefano Zampini   {
8008b9b85e73SStefano Zampini     PetscViewer viewer;
8009b9b85e73SStefano Zampini     char filename[256];
8010b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8011b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
80126a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8013b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8014f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8015b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8016b9b85e73SStefano Zampini   }
8017b9b85e73SStefano Zampini #endif
8018f9eb5b7dSStefano Zampini 
801998a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
802098a51de6SStefano Zampini     Vec crhs,csol;
802104708bb6SStefano Zampini 
8022f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8023f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8024f347579bSStefano Zampini     if (!csol) {
80252a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8026f9eb5b7dSStefano Zampini     }
8027f347579bSStefano Zampini     if (!crhs) {
80282a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8029f347579bSStefano Zampini     }
8030b0f5fe93SStefano Zampini   }
80311ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8032b0f5fe93SStefano Zampini 
8033b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8034b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8035b0f5fe93SStefano Zampini 
8036b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
80374f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
80384f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
80394f1b2e48SStefano Zampini     }
8040b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8041b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8042b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8043b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8044b0f5fe93SStefano Zampini     if (coarse_mat) {
8045b0f5fe93SStefano Zampini       Vec         nullv;
8046b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8047b0f5fe93SStefano Zampini       PetscInt    nl;
8048b0f5fe93SStefano Zampini 
8049b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8050b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8051b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8052b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8053b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8054b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8055b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8056b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8057b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8058b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8059b0f5fe93SStefano Zampini     }
8060b0f5fe93SStefano Zampini   }
8061b0f5fe93SStefano Zampini 
8062b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8063b0f5fe93SStefano Zampini     PetscBool ispreonly;
8064b0f5fe93SStefano Zampini 
8065b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8066b0f5fe93SStefano Zampini       PetscBool isnull;
8067b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8068bef83e63SStefano Zampini       if (isnull) {
8069b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8070b0f5fe93SStefano Zampini       }
8071bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8072b0f5fe93SStefano Zampini     }
8073b0f5fe93SStefano Zampini     /* setup coarse ksp */
8074b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8075cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8076cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
80776e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8078c8587f34SStefano Zampini       KSP       check_ksp;
80792b510759SStefano Zampini       KSPType   check_ksp_type;
8080c8587f34SStefano Zampini       PC        check_pc;
80816e683305SStefano Zampini       Vec       check_vec,coarse_vec;
80826a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
80832b510759SStefano Zampini       PetscInt  its;
80846e683305SStefano Zampini       PetscBool compute_eigs;
80856e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
80866e683305SStefano Zampini       PetscInt  neigs;
80878e185a42SStefano Zampini       const char *prefix;
8088c8587f34SStefano Zampini 
80892b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
80906e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
8091422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
809223ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8093f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8094e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8095e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8096e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
80972b510759SStefano Zampini       if (ispreonly) {
80982b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
80996e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
81002b510759SStefano Zampini       } else {
8101cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
81026e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8103c8587f34SStefano Zampini       }
8104c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
81056e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
81066e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
81076e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8108a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8109a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8110a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8111a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8112c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8113c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8114c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8115c8587f34SStefano Zampini       /* create random vec */
81162701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8117c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
81186e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8119c8587f34SStefano Zampini       /* solve coarse problem */
81206e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8121cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
81226e683305SStefano Zampini       if (compute_eigs) {
8123854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8124854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
81256e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
81261ae86dd6SStefano Zampini         if (neigs) {
81276e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
81286e683305SStefano Zampini           lambda_min = eigs_r[0];
81296e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
81302701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
81312701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8132cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8133cbcc2c2aSStefano Zampini             }
8134c8587f34SStefano Zampini           }
8135c8587f34SStefano Zampini         }
81361ae86dd6SStefano Zampini       }
8137cbcc2c2aSStefano Zampini 
8138c8587f34SStefano Zampini       /* check coarse problem residual error */
81396e683305SStefano Zampini       if (pcbddc->dbg_flag) {
81406e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
81416e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
81426e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8143c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
81446e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
81456e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8146779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
81476e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
81486e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
81496e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
81506e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8151b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8152b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8153b0f5fe93SStefano Zampini         }
81546e683305SStefano Zampini         if (compute_eigs) {
81556e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8156b03ebc13SStefano Zampini           KSPConvergedReason reason;
8157deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8158c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8159b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
81606e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8161b03ebc13SStefano 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);
81626e683305SStefano Zampini           for (i=0;i<neigs;i++) {
81636e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8164c8587f34SStefano Zampini           }
81656e683305SStefano Zampini         }
81666e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
81676e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
81686e683305SStefano Zampini       }
8169e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
81702701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8171c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
81726e683305SStefano Zampini       if (compute_eigs) {
81736e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
81746e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8175c8587f34SStefano Zampini       }
81766e683305SStefano Zampini     }
81776e683305SStefano Zampini   }
8178bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8179cbcc2c2aSStefano Zampini   /* print additional info */
8180cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
81816e683305SStefano Zampini     /* waits until all processes reaches this point */
81826e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
8183cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
8184cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8185cbcc2c2aSStefano Zampini   }
8186cbcc2c2aSStefano Zampini 
81872b510759SStefano Zampini   /* free memory */
8188fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
8189c8587f34SStefano Zampini   PetscFunctionReturn(0);
8190c8587f34SStefano Zampini }
8191674ae819SStefano Zampini 
8192f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8193f34684f1SStefano Zampini {
8194f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8195f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8196f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8197dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8198dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
819973be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8200dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8201f34684f1SStefano Zampini   PetscErrorCode ierr;
8202f34684f1SStefano Zampini 
8203f34684f1SStefano Zampini   PetscFunctionBegin;
8204f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
82056c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8206dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
82073bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8208dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8209dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
82106583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8211dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8212dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8213dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
82146c4ed002SBarry 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);
8215dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8216dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8217dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8218dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8219dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8220f34684f1SStefano Zampini 
8221f34684f1SStefano Zampini   /* check numbering */
8222f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8223019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8224dc456d91SStefano Zampini     PetscInt    i;
8225b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8226f34684f1SStefano Zampini 
8227f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8228f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8229f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
82301575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8231019a44ceSStefano Zampini     /* counter */
8232019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8233019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8234019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8235019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8236019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8237019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8238f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8239f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8240727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8241f34684f1SStefano Zampini     }
8242f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8243f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8244f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8245e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8246e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8247e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8248e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8249f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8250019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8251f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8252019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
82532c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
825475c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8255b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
82562c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
82572c66d082SStefano 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);
8258f34684f1SStefano Zampini       }
8259f34684f1SStefano Zampini     }
8260019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8261b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8262f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8263f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8264f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8265f34684f1SStefano Zampini     }
8266f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8267f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8268e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8269e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8270f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8271f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8272b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8273ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8274ca8b9ea9SStefano Zampini 
8275ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
82763bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8277f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8278f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8279f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8280f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
82814bc2dc4bSStefano 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);
8282f34684f1SStefano Zampini       }
8283f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8284ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8285f34684f1SStefano Zampini     }
8286f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
82871575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8288302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8289f34684f1SStefano Zampini   }
82908bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8291f34684f1SStefano Zampini   /* get back data */
8292f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8293f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8294674ae819SStefano Zampini   PetscFunctionReturn(0);
8295674ae819SStefano Zampini }
8296674ae819SStefano Zampini 
8297a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8298e456f2a8SStefano Zampini {
8299e456f2a8SStefano Zampini   IS             localis_t;
8300a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8301e456f2a8SStefano Zampini   PetscScalar    *vals;
8302e456f2a8SStefano Zampini   PetscErrorCode ierr;
8303e456f2a8SStefano Zampini 
8304e456f2a8SStefano Zampini   PetscFunctionBegin;
8305a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8306e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8307854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8308e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8309e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8310a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8311a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
83121035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
83133151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8314a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
83151035eff8SStefano Zampini   }
8316a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8317e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8318e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8319a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8320a7dc3881SStefano Zampini   /* now compute set in local ordering */
8321a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8322a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8323a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8324a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8325a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8326ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8327e456f2a8SStefano Zampini       lsize++;
8328e456f2a8SStefano Zampini     }
8329e456f2a8SStefano Zampini   }
8330854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8331a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8332ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8333e456f2a8SStefano Zampini       idxs[lsize++] = i;
8334e456f2a8SStefano Zampini     }
8335e456f2a8SStefano Zampini   }
8336a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8337a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8338e456f2a8SStefano Zampini   *localis = localis_t;
8339e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8340e456f2a8SStefano Zampini }
8341906d46d4SStefano Zampini 
834208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8343b96c3477SStefano Zampini {
8344a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8345b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8346b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8347a64f4aa4SStefano Zampini   Mat                 S_j;
8348b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8349b96c3477SStefano Zampini   PetscBool           free_used_adj;
8350b96c3477SStefano Zampini   PetscErrorCode      ierr;
8351b96c3477SStefano Zampini 
8352b96c3477SStefano Zampini   PetscFunctionBegin;
8353b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8354b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
835508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8356b96c3477SStefano Zampini     used_xadj = NULL;
8357b96c3477SStefano Zampini     used_adjncy = NULL;
8358b96c3477SStefano Zampini   } else {
835908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
836008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
836108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
836208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8363b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8364b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8365b96c3477SStefano Zampini     } else {
83662fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8367b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8368b96c3477SStefano Zampini       PetscInt       nvtxs;
8369b96c3477SStefano Zampini 
83702fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
83712fffb893SStefano Zampini       if (flg_row) {
8372b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8373b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8374b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8375b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
83762fffb893SStefano Zampini       } else {
83772fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
83782fffb893SStefano Zampini         used_xadj = NULL;
83792fffb893SStefano Zampini         used_adjncy = NULL;
83802fffb893SStefano Zampini       }
83812fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8382b96c3477SStefano Zampini     }
8383b96c3477SStefano Zampini   }
8384d5574798SStefano Zampini 
8385d5574798SStefano Zampini   /* setup sub_schurs data */
8386a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8387df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8388df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8389a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
839091af6908SStefano 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);
8391a64f4aa4SStefano Zampini   } else {
839272b8c272SStefano Zampini     Mat       change = NULL;
83939d54b7f4SStefano Zampini     Vec       scaling = NULL;
8394111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8395111315fdSstefano_zampini     PetscInt  benign_n;
8396111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8397111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8398111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8399a3df083aSStefano Zampini 
84005feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
84015feab87aSStefano Zampini       PetscInt n_vertices;
84025feab87aSStefano Zampini 
84035feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
84042034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
84055feab87aSStefano Zampini     }
840604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
840704708bb6SStefano Zampini     if (!isseqaij) {
840804708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
840904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
841004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
841104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
841204708bb6SStefano Zampini       } else {
8413511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
841404708bb6SStefano Zampini       }
841504708bb6SStefano Zampini     }
8416a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8417a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8418ca92afb2SStefano Zampini     } else {
8419a3df083aSStefano Zampini       benign_n = 0;
8420ca92afb2SStefano Zampini     }
8421b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8422b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8423b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
842472b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
842522db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8426b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
842722db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8428b7ab4a40SStefano Zampini     }
8429b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8430b7ab4a40SStefano 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 */
8431b7ab4a40SStefano Zampini     if (need_change) {
843288c03ad3SStefano Zampini       PC_IS   *pcisf;
843388c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
843488c03ad3SStefano Zampini       PC      pcf;
843588c03ad3SStefano Zampini 
8436e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
843788c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
843888c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
843988c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8440b9be95fcSstefano_zampini 
844188c03ad3SStefano Zampini       /* hacks */
844288c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
844372b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
844472b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
844572b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
844672b8c272SStefano Zampini       pcisf->n                     = pcis->n;
844772b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
844888c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
844988c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
845088c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
845188c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
845288c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
845388c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
845472b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
845588c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8456b9be95fcSstefano_zampini 
8457b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
845888c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
845972b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
846072b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
846172b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
846272b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8463b9be95fcSstefano_zampini 
846488c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
846572b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
846688c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
846788c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
846888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
846988c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
847088c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
847188c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8472b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
847388c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
847488c03ad3SStefano Zampini     }
84759d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8476111315fdSstefano_zampini 
8477111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8478111315fdSstefano_zampini     if (iP) {
8479111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8480111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8481111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8482111315fdSstefano_zampini     }
8483111315fdSstefano_zampini     if (discrete_harmonic) {
8484111315fdSstefano_zampini       Mat A;
8485111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8486111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8487111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8488111315fdSstefano_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);
8489111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8490111315fdSstefano_zampini     } else {
849191af6908SStefano 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);
8492111315fdSstefano_zampini     }
849372b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
849472b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8495ca92afb2SStefano Zampini   }
8496d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8497b96c3477SStefano Zampini 
8498b96c3477SStefano Zampini   /* free adjacency */
8499b96c3477SStefano Zampini   if (free_used_adj) {
8500b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8501b96c3477SStefano Zampini   }
8502b96c3477SStefano Zampini   PetscFunctionReturn(0);
8503b96c3477SStefano Zampini }
8504b96c3477SStefano Zampini 
850508122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8506b96c3477SStefano Zampini {
8507b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8508b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8509b96c3477SStefano Zampini   PCBDDCGraph         graph;
8510b96c3477SStefano Zampini   PetscErrorCode      ierr;
8511b96c3477SStefano Zampini 
8512b96c3477SStefano Zampini   PetscFunctionBegin;
8513b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
851408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
85153301b35fSStefano Zampini     IS       verticesIS,verticescomm;
85163301b35fSStefano Zampini     PetscInt vsize,*idxs;
8517b96c3477SStefano Zampini 
8518b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
85193301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
85203301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
85213301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
85223301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8523c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8524b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8525be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8526441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
85273301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8528b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8529b96c3477SStefano Zampini   } else {
8530b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8531b96c3477SStefano Zampini   }
8532e4d548c7SStefano Zampini   /* print some info */
85335c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8534e4d548c7SStefano Zampini     IS       vertices;
8535e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8536c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8537e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8538e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8539e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8540e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8541e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8542e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8543e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8544e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8545e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8546c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8547e4d548c7SStefano Zampini   }
8548b96c3477SStefano Zampini 
8549b96c3477SStefano Zampini   /* sub_schurs init */
8550b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8551b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8552b334f244SStefano Zampini   }
855388113c35SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,((PetscObject)pc)->prefix,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
8554a64f4aa4SStefano Zampini 
8555b96c3477SStefano Zampini   /* free graph struct */
855608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8557b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8558b96c3477SStefano Zampini   }
8559b96c3477SStefano Zampini   PetscFunctionReturn(0);
8560b96c3477SStefano Zampini }
8561fa34dd3eSStefano Zampini 
8562fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8563fa34dd3eSStefano Zampini {
8564fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8565fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8566fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8567fa34dd3eSStefano Zampini 
8568fa34dd3eSStefano Zampini   PetscFunctionBegin;
8569fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8570fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
85714f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8572fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
85734f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
857475c01103SStefano Zampini     PetscReal      norm;
8575fa34dd3eSStefano Zampini     PetscInt       i;
8576fa34dd3eSStefano Zampini 
8577fa34dd3eSStefano Zampini     /* B0 and B0_B */
8578fa34dd3eSStefano Zampini     if (zerodiag) {
8579fa34dd3eSStefano Zampini       IS       dummy;
8580fa34dd3eSStefano Zampini 
85814f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
85827dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8583fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8584fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8585fa34dd3eSStefano Zampini     }
8586fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8587fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8588fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8589fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8590fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8591fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8592fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8593fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8594fa34dd3eSStefano Zampini     /* S_j */
8595fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8596fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8597fa34dd3eSStefano Zampini 
8598fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8599fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8600fa34dd3eSStefano Zampini     /* continuous in primal space */
8601fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8602fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8603fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8604fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
86054f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
86064f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8607fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8608fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8609fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8610fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8611fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8612fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8613fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8614fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8615fa34dd3eSStefano Zampini 
8616fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8617fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8618fa34dd3eSStefano Zampini     /* local with Schur */
8619fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8620fa34dd3eSStefano Zampini     if (zerodiag) {
8621fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
86224f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8623fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8624fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8625fa34dd3eSStefano Zampini     }
8626fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8627fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8628fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8629fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8630fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8631fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8632fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8633fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8634fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8635fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8636fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8637fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8638fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8639fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8640fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8641fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8642fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8643fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8644fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8645fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8646fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8647fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8648fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8649fa34dd3eSStefano Zampini     if (zerodiag) {
8650fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8651fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
86524f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8653fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8654fa34dd3eSStefano Zampini     }
8655fa34dd3eSStefano Zampini     /* BDDC */
8656fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8657fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8658fa34dd3eSStefano Zampini 
8659fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8660fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8661fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8662fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
86634f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
86644f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8665fa34dd3eSStefano Zampini     }
86664f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8667fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8668fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8669fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8670fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8671fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8672fa34dd3eSStefano Zampini   }
8673fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8674fa34dd3eSStefano Zampini }
86751e0482f5SStefano Zampini 
86761e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
86771e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
86781e0482f5SStefano Zampini {
86791e0482f5SStefano Zampini   Mat            At;
86801e0482f5SStefano Zampini   IS             rows;
86811e0482f5SStefano Zampini   PetscInt       rst,ren;
86821e0482f5SStefano Zampini   PetscErrorCode ierr;
86831e0482f5SStefano Zampini   PetscLayout    rmap;
86841e0482f5SStefano Zampini 
86851e0482f5SStefano Zampini   PetscFunctionBegin;
86861e0482f5SStefano Zampini   rst = ren = 0;
86871e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
86881e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
86891e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
86901e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
86911e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
86921e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
86931e0482f5SStefano Zampini   }
8694e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
86957dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
86961e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
86971e0482f5SStefano Zampini 
86981e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
86991e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
87001e0482f5SStefano Zampini     IS         from,to;
87011e0482f5SStefano Zampini     Vec        gvec;
87021e0482f5SStefano Zampini     PetscInt   lsize;
87031e0482f5SStefano Zampini 
87041e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
87051e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
87061e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
87071e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
87081e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
87091e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
87101e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
87111e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
87121e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
87131e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
87141e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
87151e0482f5SStefano Zampini     b->A = a->A;
87161e0482f5SStefano Zampini     b->B = a->B;
87171e0482f5SStefano Zampini 
87181e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
87191e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
87201e0482f5SStefano Zampini     b->rowindices      = 0;
87211e0482f5SStefano Zampini     b->rowvalues       = 0;
87221e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
87231e0482f5SStefano Zampini 
87241e0482f5SStefano Zampini     (*B)->rmap         = rmap;
87251e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
87261e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
87271e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
87281e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
87291e0482f5SStefano Zampini 
87301e0482f5SStefano Zampini     if (a->colmap) {
87311e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
87321e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
87331e0482f5SStefano Zampini #else
87341e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
87351e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
87361e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
87371e0482f5SStefano Zampini #endif
87381e0482f5SStefano Zampini     } else b->colmap = 0;
87391e0482f5SStefano Zampini     if (a->garray) {
87401e0482f5SStefano Zampini       PetscInt len;
87411e0482f5SStefano Zampini       len  = a->B->cmap->n;
87421e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
87431e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
87441e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
87451e0482f5SStefano Zampini     } else b->garray = 0;
87461e0482f5SStefano Zampini 
87471e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
87481e0482f5SStefano Zampini     b->lvec = a->lvec;
87491e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
87501e0482f5SStefano Zampini 
87511e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
87521e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
87531e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
87541e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
87551e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
87561e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
87571e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
87581e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
87591e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
87601e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
87611e0482f5SStefano Zampini   }
87621e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
87631e0482f5SStefano Zampini   PetscFunctionReturn(0);
87641e0482f5SStefano Zampini }
8765