xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 487b449ae26429168dbcf793c15988ececac9918)
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 */
457b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
458b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini 
4607d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4617d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
46262b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
46362b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
464b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
46562b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
46662b0c6f7SStefano Zampini     }
46762b0c6f7SStefano Zampini   }
468637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
46962b0c6f7SStefano Zampini   if (!conforming) {
47062b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
47162b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
47262b0c6f7SStefano Zampini   }
4734e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
474dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
47562b0c6f7SStefano Zampini   cum  = 0;
476a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
477dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47862b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
479a13144ffSStefano Zampini       marks[cum++] = i;
480dec27d64SStefano Zampini       continue;
481dec27d64SStefano Zampini     }
482dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
48362b0c6f7SStefano Zampini     if (!conforming) {
48462b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
485a13144ffSStefano Zampini         marks[cum++] = i;
486a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
487a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
488a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
489a13144ffSStefano Zampini         }
49062b0c6f7SStefano Zampini       } else {
49162b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
49262b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
49362b0c6f7SStefano Zampini            - at most 2 endpoints
49462b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49562b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49662b0c6f7SStefano Zampini         */
49762b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49862b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49962b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
50062b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
50162b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
50262b0c6f7SStefano Zampini           if (nconn > order) ends++;
50362b0c6f7SStefano Zampini           else if (nconn == order) ints++;
50462b0c6f7SStefano Zampini           else undef++;
50562b0c6f7SStefano Zampini         }
50662b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50762b0c6f7SStefano Zampini           marks[cum++] = i;
50862b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
50962b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
51062b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini           }
51262b0c6f7SStefano Zampini         }
51362b0c6f7SStefano Zampini       }
514a13144ffSStefano Zampini     }
515dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
516dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
517dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
518dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
519a13144ffSStefano Zampini     }
520dec27d64SStefano Zampini   }
52162b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5234e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
52462b0c6f7SStefano Zampini   if (!conforming) {
52562b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52662b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
52762b0c6f7SStefano Zampini   }
5284e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
529637e8532SStefano Zampini 
530b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5314e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
532a13144ffSStefano Zampini   if (print) {
5334e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5344e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5354e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
536a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
537a13144ffSStefano Zampini   }
538a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
539dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
540a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
541637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5427d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
543b03ebc13SStefano Zampini     if (!order) { /* variable order */
544dec27d64SStefano Zampini       PetscReal vorder = 0.;
545dec27d64SStefano Zampini 
546dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
547dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
548dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
549dec27d64SStefano Zampini       ord  = 1;
550dec27d64SStefano Zampini     }
551a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
552dec27d64SStefano 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);
553a13144ffSStefano Zampini #endif
554637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5557d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5567d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5577d871cd7SStefano Zampini         break;
5587d871cd7SStefano Zampini       }
559637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
560637e8532SStefano Zampini         sneighs = PETSC_FALSE;
561637e8532SStefano Zampini       } else {
562637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
563637e8532SStefano Zampini         for (k=0;k<vc;k++) {
564637e8532SStefano Zampini           if (vn[k] != en[k]) {
565637e8532SStefano Zampini             sneighs = PETSC_FALSE;
566637e8532SStefano Zampini             break;
567637e8532SStefano Zampini           }
568637e8532SStefano Zampini         }
569637e8532SStefano Zampini       }
570637e8532SStefano Zampini     }
5717d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5727d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
573a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
574dec27d64SStefano Zampini     } else if (test == ord) {
575b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
576a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
577a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
578a13144ffSStefano Zampini       } else {
579a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
580a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
581a13144ffSStefano Zampini       }
582a13144ffSStefano Zampini     }
583a13144ffSStefano Zampini   }
584b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
585b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
5867d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
587b03ebc13SStefano Zampini 
588b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
589b03ebc13SStefano Zampini   if (order != 1) {
590b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
591b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
592b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
593b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
594b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
595b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
596b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
597b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
598b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
599b03ebc13SStefano Zampini             PetscInt v = jjt[k];
600b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
601b03ebc13SStefano Zampini               found = PETSC_TRUE;
602b03ebc13SStefano Zampini               break;
603b03ebc13SStefano Zampini             }
604b03ebc13SStefano Zampini           }
605b03ebc13SStefano Zampini         }
606b03ebc13SStefano Zampini         if (!found) {
607b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
608b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
609b03ebc13SStefano Zampini         } else {
610b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
611b03ebc13SStefano Zampini         }
612b03ebc13SStefano Zampini       }
613b03ebc13SStefano Zampini     }
614b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
615b03ebc13SStefano Zampini   }
616dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
617a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
618b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
619a13144ffSStefano Zampini 
620a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6210569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
622a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6234e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
624a13144ffSStefano Zampini 
6254e64d54eSstefano_zampini   /* Mark interior nodal dofs */
626a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6274e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
628a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
629a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6304e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
631a13144ffSStefano Zampini     }
632a13144ffSStefano Zampini   }
633a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
634a13144ffSStefano Zampini 
635a13144ffSStefano Zampini   /* communicate corners and splitpoints */
636a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
637a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
638a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
639a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
640a13144ffSStefano Zampini 
641a13144ffSStefano Zampini   if (print) {
642a13144ffSStefano Zampini     IS tbz;
643a13144ffSStefano Zampini 
644a13144ffSStefano Zampini     cum = 0;
645a13144ffSStefano Zampini     for (i=0;i<nv;i++)
646a13144ffSStefano Zampini       if (sfvleaves[i])
647a13144ffSStefano Zampini         vmarks[cum++] = i;
648a13144ffSStefano Zampini 
649a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
650a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
651a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
652a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
653a13144ffSStefano Zampini   }
654a13144ffSStefano Zampini 
655a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
656a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
657a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
658a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
659a13144ffSStefano Zampini 
6604e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6614e64d54eSstefano_zampini      and interior nodal dofs */
662a13144ffSStefano Zampini   cum = 0;
663a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
664a13144ffSStefano Zampini     if (sfvleaves[i]) {
665a13144ffSStefano Zampini       vmarks[cum++] = i;
666a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
667a13144ffSStefano Zampini     }
6684e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
669a13144ffSStefano Zampini   }
6704e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
671a13144ffSStefano Zampini   if (print) {
672a13144ffSStefano Zampini     IS tbz;
673a13144ffSStefano Zampini 
674a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6754e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
676a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
677a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
678a13144ffSStefano Zampini   }
679a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
680a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
681a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
682a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
683a13144ffSStefano Zampini 
684a13144ffSStefano Zampini   /* Recompute G */
685a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
686a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
687a13144ffSStefano Zampini   if (print) {
688a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
689a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
690a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
691a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
692a13144ffSStefano Zampini   }
693a13144ffSStefano Zampini 
694a13144ffSStefano Zampini   /* Get primal dofs (if any) */
695a13144ffSStefano Zampini   cum = 0;
696a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
697a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
698a13144ffSStefano Zampini   }
699c2151214SStefano Zampini   if (fl2g) {
700c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
701c2151214SStefano Zampini   }
702a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
703a13144ffSStefano Zampini   if (print) {
704a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
705a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
706a13144ffSStefano Zampini   }
707a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
708c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
709a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
710a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
711a13144ffSStefano Zampini 
712a13144ffSStefano Zampini   /* Compute edge connectivity */
713a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
715a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
716c2151214SStefano Zampini   if (fl2g) {
717c2151214SStefano Zampini     PetscBT   btf;
718c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
719c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
720c2151214SStefano Zampini 
721c2151214SStefano Zampini     /* create CSR for all local dofs */
722c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
723c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
724c2151214SStefano 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);
725c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
726c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
727c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
728c2151214SStefano Zampini       rest = PETSC_TRUE;
729c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
730c2151214SStefano Zampini     } else {
731c2151214SStefano Zampini       free   = PETSC_TRUE;
732c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
733c2151214SStefano Zampini       iiu[0] = 0;
734c2151214SStefano Zampini       for (i=0;i<n;i++) {
735c2151214SStefano Zampini         iiu[i+1] = i+1;
736c2151214SStefano Zampini         jju[i]   = -1;
737d904f53bSStefano Zampini       }
738c2151214SStefano Zampini     }
739c2151214SStefano Zampini 
740c2151214SStefano Zampini     /* import sizes of CSR */
741c2151214SStefano Zampini     iia[0] = 0;
742c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
743c2151214SStefano Zampini 
744c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
745c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
746c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
747c2151214SStefano Zampini     for (i=0;i<ne;i++) {
748c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
749c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
750c2151214SStefano Zampini     }
751c2151214SStefano Zampini 
752c2151214SStefano Zampini     /* iia in CSR */
753c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
754c2151214SStefano Zampini 
755c2151214SStefano Zampini     /* jja in CSR */
756c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
757c2151214SStefano Zampini     for (i=0;i<n;i++)
758c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
759c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
760c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
761c2151214SStefano Zampini 
762c2151214SStefano Zampini     /* map edge dofs connectivity */
7631e0482f5SStefano Zampini     if (jj) {
764c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
765c2151214SStefano Zampini       for (i=0;i<ne;i++) {
766c2151214SStefano Zampini         PetscInt e = idxs[i];
767c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
768c2151214SStefano Zampini       }
7691e0482f5SStefano Zampini     }
770c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
771c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
772c2151214SStefano Zampini     if (rest) {
773c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
774c2151214SStefano Zampini     }
775c2151214SStefano Zampini     if (free) {
776c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
777c2151214SStefano Zampini     }
778c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
779c2151214SStefano Zampini   } else {
780c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
781c2151214SStefano Zampini   }
782c2151214SStefano Zampini 
783a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
784a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
785213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
786a13144ffSStefano Zampini 
787a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
788c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
789a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
790a13144ffSStefano Zampini 
791c2151214SStefano Zampini   if (fl2g) {
792c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
793c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
794c2151214SStefano Zampini     for (i=0;i<nee;i++) {
795c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
796c2151214SStefano Zampini     }
797c2151214SStefano Zampini   } else {
798c2151214SStefano Zampini     eedges  = alleedges;
799c2151214SStefano Zampini     primals = allprimals;
800c2151214SStefano Zampini   }
801c2151214SStefano Zampini 
802a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
803a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
804c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
805c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
806c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
807c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
808c2151214SStefano Zampini   if (print) {
809c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
810c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
811c2151214SStefano Zampini   }
812c2151214SStefano Zampini 
813c2151214SStefano Zampini   maxsize = 0;
814a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
815a13144ffSStefano Zampini     PetscInt size,mark = i+1;
816a13144ffSStefano Zampini 
817a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
818a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
819a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
820a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
821a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
822a13144ffSStefano Zampini   }
823a13144ffSStefano Zampini 
824a13144ffSStefano Zampini   /* Find coarse edge endpoints */
825a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
826a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
827a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
828a13144ffSStefano Zampini     PetscInt mark = i+1,size;
829a13144ffSStefano Zampini 
830a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8311e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8321e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
833a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
834a13144ffSStefano Zampini     if (print) {
835a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
836a13144ffSStefano Zampini       ISView(eedges[i],NULL);
837a13144ffSStefano Zampini     }
838a13144ffSStefano Zampini     for (j=0;j<size;j++) {
839a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
840a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
841a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
842a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
843a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
844a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
845a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
846a13144ffSStefano Zampini           PetscInt  k2;
847a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
848a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
849c2151214SStefano 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]));
850c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
851c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
852c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
853a13144ffSStefano Zampini               corner = PETSC_TRUE;
854a13144ffSStefano Zampini               break;
855a13144ffSStefano Zampini             }
856a13144ffSStefano Zampini           }
857a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
858a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
859a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
860a13144ffSStefano Zampini           } else {
861a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
862a13144ffSStefano Zampini           }
863a13144ffSStefano Zampini         }
864a13144ffSStefano Zampini       }
865a13144ffSStefano Zampini     }
866a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
867a13144ffSStefano Zampini   }
868a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
869a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
870c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
871a13144ffSStefano Zampini 
872a13144ffSStefano Zampini   /* Reset marked primal dofs */
873a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
874a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
876a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini 
8780569b399SStefano Zampini   /* Now use the initial lG */
8790569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8800569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8810569b399SStefano Zampini   lG   = lGinit;
8820569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8830569b399SStefano Zampini 
884a13144ffSStefano Zampini   /* Compute extended cols indices */
885b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
886b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
887a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
888a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
889a13144ffSStefano Zampini   i   *= maxsize;
890b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
891a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
892a13144ffSStefano Zampini   eerr = PETSC_FALSE;
893a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
894b03ebc13SStefano Zampini     PetscInt size,found = 0;
895a13144ffSStefano Zampini 
896a13144ffSStefano Zampini     cum  = 0;
897a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8981e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8991e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
900a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
901b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
902a13144ffSStefano Zampini     for (j=0;j<size;j++) {
903a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
904b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
905b03ebc13SStefano Zampini         PetscInt vv = jj[k];
906b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
907b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
908b03ebc13SStefano Zampini       }
909a13144ffSStefano Zampini     }
910a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
911a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
912a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
913a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
914a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
915a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
916a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
917b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
918b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
919a13144ffSStefano Zampini       if (print) {
920a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
921a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
922a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
923a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
924a13144ffSStefano Zampini       }
925a13144ffSStefano Zampini       eerr = PETSC_TRUE;
926a13144ffSStefano Zampini     }
927a13144ffSStefano Zampini   }
9284e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
929a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
930a13144ffSStefano Zampini   if (done) {
931a13144ffSStefano Zampini     PetscInt *newprimals;
932a13144ffSStefano Zampini 
933a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
934a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
935a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
936a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
937a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9380569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
939b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
940a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
941b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
942b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
943a13144ffSStefano Zampini         PetscInt size,mark = i+1;
944a13144ffSStefano Zampini 
945a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
946a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
947c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
948a13144ffSStefano Zampini         for (j=0;j<size;j++) {
949a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
950b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
951a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
952a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
953a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
954a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
955b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
956b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
957a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
958a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
959a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
960a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
961a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
962b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
963a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
964a13144ffSStefano Zampini                   /* finally set the new corners */
965a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
966b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
967a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
968a13144ffSStefano Zampini                   }
969a13144ffSStefano Zampini                 }
970a13144ffSStefano Zampini               }
971b03ebc13SStefano Zampini             } else {
972b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
973a13144ffSStefano Zampini             }
974a13144ffSStefano Zampini           }
975a13144ffSStefano Zampini         }
976b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
977b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
978b03ebc13SStefano Zampini 
979b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
980b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
981b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
982b03ebc13SStefano Zampini             PetscInt k2;
983b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
984b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
985b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
986b03ebc13SStefano Zampini           }
987b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
988b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
989b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
990b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
991b03ebc13SStefano Zampini             }
992b03ebc13SStefano Zampini           }
993b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
994b03ebc13SStefano Zampini         }
995a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
996a13144ffSStefano Zampini       }
997a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
998a13144ffSStefano Zampini     }
999b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10000569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1001a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1002c2151214SStefano Zampini     if (fl2g) {
1003c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1004c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1005c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1006c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1007c2151214SStefano Zampini       }
1008c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1009c2151214SStefano Zampini     }
1010c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1011a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1012a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1013a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1014a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1015a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1016213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1017c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1018c2151214SStefano Zampini     if (fl2g) {
1019c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1020c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1021c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1022c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1023c2151214SStefano Zampini       }
1024c2151214SStefano Zampini     } else {
1025c2151214SStefano Zampini       eedges  = alleedges;
1026c2151214SStefano Zampini       primals = allprimals;
1027c2151214SStefano Zampini     }
1028b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1029a13144ffSStefano Zampini 
1030a13144ffSStefano Zampini     /* Mark again */
1031a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1032a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1033a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1034a13144ffSStefano Zampini 
1035a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1036a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1037a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1038a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1039a13144ffSStefano Zampini     }
1040a13144ffSStefano Zampini     if (print) {
1041a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1042a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1043a13144ffSStefano Zampini     }
1044a13144ffSStefano Zampini 
1045a13144ffSStefano Zampini     /* Recompute extended cols */
1046a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1047a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1048a13144ffSStefano Zampini       PetscInt size;
1049a13144ffSStefano Zampini 
1050a13144ffSStefano Zampini       cum  = 0;
1051a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10521e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10531e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1054a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1055a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1056a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10571e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1058a13144ffSStefano Zampini       }
1059a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1060a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1061a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1062a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1063a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1064a13144ffSStefano Zampini       if (cum != size -1) {
1065a13144ffSStefano Zampini         if (print) {
1066a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1067a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1068a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1069a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1070a13144ffSStefano Zampini         }
1071a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1072a13144ffSStefano Zampini       }
1073a13144ffSStefano Zampini     }
1074a13144ffSStefano Zampini   }
1075a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1076a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1077b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
10787d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1079a13144ffSStefano Zampini   /* an error should not occur at this point */
1080a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1081a13144ffSStefano Zampini 
10824e64d54eSstefano_zampini   /* Check the number of endpoints */
10830569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1084b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1085b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10864e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1087b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10884e64d54eSstefano_zampini 
1089b03ebc13SStefano Zampini     /* init with defaults */
1090b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10914e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10921e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10931e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
10944e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
10964e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10974e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10984e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10994e64d54eSstefano_zampini         PetscInt vv = jj[k];
11004e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1101b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1102b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11034e64d54eSstefano_zampini         }
11044e64d54eSstefano_zampini       }
11054e64d54eSstefano_zampini     }
1106b03ebc13SStefano Zampini     if (found != 2) {
1107b03ebc13SStefano Zampini       PetscInt e;
1108b03ebc13SStefano Zampini       if (fl2g) {
1109b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1110b03ebc13SStefano Zampini       } else {
1111b03ebc13SStefano Zampini         e = idxs[0];
1112b03ebc13SStefano Zampini       }
1113b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1114b03ebc13SStefano Zampini     }
1115eee23b56SStefano Zampini 
1116eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1117b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1118b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1119b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1120b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1121b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1122b03ebc13SStefano Zampini     }
1123eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11244e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1125b03ebc13SStefano 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]);
11264e64d54eSstefano_zampini   }
11270569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11284e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11294e64d54eSstefano_zampini 
1130a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1131a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1132a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1133a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1134a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1135a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1136a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1137a13144ffSStefano Zampini 
1138a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1139a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1140a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1141a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1142a13144ffSStefano Zampini       if (emax < emarks[j]) {
1143a13144ffSStefano Zampini         emax = emarks[j];
1144a13144ffSStefano Zampini         eemax = j;
1145a13144ffSStefano Zampini       }
1146a13144ffSStefano Zampini     }
1147a13144ffSStefano Zampini     /* not relevant for edges */
1148a13144ffSStefano Zampini     if (!eemax) continue;
1149a13144ffSStefano Zampini 
1150a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1151a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1152c2151214SStefano 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]);
1153a13144ffSStefano Zampini       }
1154a13144ffSStefano Zampini     }
1155a13144ffSStefano Zampini   }
1156a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1157a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1158a13144ffSStefano Zampini #endif
1159a13144ffSStefano Zampini 
1160a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1161a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1162a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1163a13144ffSStefano Zampini   extmem *= maxsize;
1164a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1165a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1166a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1167a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1168a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1169213b8bfaSStefano Zampini 
1170a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1171a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1172a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1173a13144ffSStefano Zampini         mark = marks[jj[j]];
1174a13144ffSStefano Zampini 
1175a13144ffSStefano Zampini     /* not relevant */
1176a13144ffSStefano Zampini     if (!mark) continue;
1177a13144ffSStefano Zampini 
1178a13144ffSStefano Zampini     /* import extended row */
1179a13144ffSStefano Zampini     mark--;
1180a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1181a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1182a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1183a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1184a13144ffSStefano Zampini     extrowcum[mark] += size;
1185a13144ffSStefano Zampini   }
1186a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1187213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1188213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1189213b8bfaSStefano Zampini 
1190213b8bfaSStefano Zampini   /* Compress extrows */
1191a13144ffSStefano Zampini   cum  = 0;
1192a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1193a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1194a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1195a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1196a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1197a13144ffSStefano Zampini   }
1198a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1199a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1200a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1201a13144ffSStefano Zampini 
1202a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1203a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1204a13144ffSStefano Zampini 
1205a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1206a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1207c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1208c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1209a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1210a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1211a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12121e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1214a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1215213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1216a13144ffSStefano Zampini 
1217a13144ffSStefano Zampini   /* Defaults to identity */
1218c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1220a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1222a13144ffSStefano Zampini 
12231e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12241e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12251e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12261e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12271e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12281e0482f5SStefano Zampini     IS                     wis,gwis;
12291e0482f5SStefano Zampini     PetscInt               cnv,cne;
12301e0482f5SStefano Zampini 
12311e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12321e0482f5SStefano Zampini     if (fl2g) {
12331e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12341e0482f5SStefano Zampini     } else {
12351e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12361e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12371e0482f5SStefano Zampini     }
12381e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12391e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12401e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12411e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12421e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12431e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12441e0482f5SStefano Zampini 
12451e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12461e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12471e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12481e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12491e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12501e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12511e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12521e0482f5SStefano Zampini 
12531e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12541e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12551e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12561e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12571e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12581e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12591e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12601e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12611e0482f5SStefano Zampini   }
1262213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
12631e0482f5SStefano Zampini 
12641e0482f5SStefano Zampini #if defined(PRINT_GDET)
12651e0482f5SStefano Zampini   inc = 0;
12661e0482f5SStefano Zampini   lev = pcbddc->current_level;
12671e0482f5SStefano Zampini #endif
1268213b8bfaSStefano Zampini 
1269213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1270a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1271a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12721e0482f5SStefano Zampini     IS          cornersis = NULL;
12731e0482f5SStefano Zampini     PetscScalar cvals[2];
1274a13144ffSStefano Zampini 
12751e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12761e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12771e0482f5SStefano Zampini     }
12781e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1279a13144ffSStefano Zampini     if (Gins && GKins) {
1280a13144ffSStefano Zampini       PetscScalar    *data;
1281a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1282a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1283a13144ffSStefano Zampini 
1284a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1285a13144ffSStefano Zampini       /* H1 */
1286a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1287a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1288a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1289a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1290a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1291a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1292a13144ffSStefano Zampini       /* complement */
1293a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12941e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1295213b8bfaSStefano 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);
1296213b8bfaSStefano 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);
1297a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1298a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1299a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini       /* coarse discrete gradient */
13021e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13031e0482f5SStefano Zampini         PetscInt cols[2];
13041e0482f5SStefano Zampini 
13051e0482f5SStefano Zampini         cols[0] = 2*i;
13061e0482f5SStefano Zampini         cols[1] = 2*i+1;
13071e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13081e0482f5SStefano Zampini       }
1309a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1310a13144ffSStefano Zampini     }
1311a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1312a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1314a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1315a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1316a13144ffSStefano Zampini   }
1317213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1318a13144ffSStefano Zampini 
1319a13144ffSStefano Zampini   /* Start assembling */
1320a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13211e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13221e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13231e0482f5SStefano Zampini   }
1324a13144ffSStefano Zampini 
1325a13144ffSStefano Zampini   /* Free */
1326c2151214SStefano Zampini   if (fl2g) {
1327c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1328c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1329c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1330c2151214SStefano Zampini     }
1331c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1332c2151214SStefano Zampini   }
1333eee23b56SStefano Zampini 
1334eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1335eee23b56SStefano Zampini   {
1336eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1337eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1338eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1339eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1340eee23b56SStefano Zampini 
1341eee23b56SStefano Zampini     /* find first primal edge */
1342eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1343eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1344eee23b56SStefano Zampini     } else {
1345eee23b56SStefano Zampini       if (fl2g) {
1346eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1347eee23b56SStefano Zampini       }
1348eee23b56SStefano Zampini       idxs = cedges;
1349eee23b56SStefano Zampini     }
1350eee23b56SStefano Zampini     cum = 0;
1351eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1352eee23b56SStefano Zampini 
1353eee23b56SStefano Zampini     /* adapt connected components */
1354eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1355eee23b56SStefano Zampini     graph->cptr[0] = 0;
1356eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1357eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1358eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1359eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1360eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1361eee23b56SStefano Zampini         ncc++;
1362eee23b56SStefano Zampini         lc--;
1363eee23b56SStefano Zampini         cum++;
1364eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1365eee23b56SStefano Zampini       }
1366eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1367eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1368eee23b56SStefano Zampini       ncc++;
1369eee23b56SStefano Zampini     }
1370eee23b56SStefano Zampini     graph->ncc = ncc;
1371eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1372eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1373eee23b56SStefano Zampini     }
1374eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1375eee23b56SStefano Zampini   }
1376213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1377c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1378c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1379213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1380eee23b56SStefano Zampini 
1381c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1382a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1383a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1384b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1385b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1386a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1387a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1388a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1389a13144ffSStefano Zampini 
1390a13144ffSStefano Zampini   /* Complete assembling */
1391a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13921e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13931e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13941e0482f5SStefano Zampini #if 0
13951e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
13961e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
13971e0482f5SStefano Zampini #endif
13981e0482f5SStefano Zampini   }
1399a13144ffSStefano Zampini 
1400a13144ffSStefano Zampini   /* set change of basis */
1401213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1402a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1403a13144ffSStefano Zampini 
1404a13144ffSStefano Zampini   PetscFunctionReturn(0);
1405a13144ffSStefano Zampini }
1406a13144ffSStefano Zampini 
1407d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1408d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1409d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1410d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1411d8203eabSStefano Zampini {
1412d8203eabSStefano Zampini   PetscErrorCode ierr;
1413d8203eabSStefano Zampini   PetscInt       i;
1414d8203eabSStefano Zampini 
1415d8203eabSStefano Zampini   PetscFunctionBegin;
1416d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1417d8203eabSStefano Zampini     PetscInt first,last;
1418d8203eabSStefano Zampini 
1419d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
142086fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1421d8203eabSStefano Zampini     if (i>=first && i < last) {
1422d8203eabSStefano Zampini       PetscScalar *data;
1423d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1424d8203eabSStefano Zampini       if (!has_const) {
1425d8203eabSStefano Zampini         data[i-first] = 1.;
1426d8203eabSStefano Zampini       } else {
142786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1429d8203eabSStefano Zampini       }
1430d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1431d8203eabSStefano Zampini     }
1432d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1433d8203eabSStefano Zampini   }
1434d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1435d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1436d8203eabSStefano Zampini     PetscInt first,last;
1437ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1438d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1439d8203eabSStefano Zampini     if (i>=first && i < last) {
1440d8203eabSStefano Zampini       PetscScalar *data;
1441d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1442d8203eabSStefano Zampini       if (!has_const) {
1443d8203eabSStefano Zampini         data[i-first] = 0.;
1444d8203eabSStefano Zampini       } else {
144586fa73c5SStefano Zampini         data[2*i-first] = 0.;
144686fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1447d8203eabSStefano Zampini       }
1448d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1449d8203eabSStefano Zampini     }
1450d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1451ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1452d8203eabSStefano Zampini   }
1453d8203eabSStefano Zampini   PetscFunctionReturn(0);
1454d8203eabSStefano Zampini }
1455d8203eabSStefano Zampini 
14568ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1457669cc0f4SStefano Zampini {
1458a198735bSStefano Zampini   Mat                    loc_divudotp;
1459fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14608ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1461669cc0f4SStefano Zampini   PetscScalar            *vals;
1462669cc0f4SStefano Zampini   const PetscScalar      *array;
1463a040e873SStefano Zampini   PetscInt               i,maxneighs,maxsize;
1464a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14651ae86dd6SStefano Zampini   PetscMPIInt            rank;
1466a198735bSStefano Zampini   PetscErrorCode         ierr;
1467669cc0f4SStefano Zampini 
1468669cc0f4SStefano Zampini   PetscFunctionBegin;
1469a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1470a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
14718037d520SStefano Zampini   if (!maxneighs) {
14728037d520SStefano Zampini     ierr  = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14738037d520SStefano Zampini     *nnsp = NULL;
14748037d520SStefano Zampini     PetscFunctionReturn(0);
1475669cc0f4SStefano Zampini   }
1476669cc0f4SStefano Zampini   maxsize = 0;
1477a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
1478669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1479669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1480669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14818ae0ca82SStefano Zampini   if (!transpose) {
14828ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14838ae0ca82SStefano Zampini   } else {
14848ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14858ae0ca82SStefano Zampini   }
1486669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14871ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1488d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1489669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1490ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
14918ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1492669cc0f4SStefano Zampini   }
1493d8203eabSStefano Zampini 
1494669cc0f4SStefano Zampini   /* compute local quad vec */
1495a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
14968ae0ca82SStefano Zampini   if (!transpose) {
1497a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
14988ae0ca82SStefano Zampini   } else {
14998ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15008ae0ca82SStefano Zampini   }
1501669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15028ae0ca82SStefano Zampini   if (!transpose) {
1503a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15048ae0ca82SStefano Zampini   } else {
15058ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15068ae0ca82SStefano Zampini   }
1507fa23a32eSStefano Zampini   if (vl2l) {
1508187c917aSStefano Zampini     Mat        lA;
1509187c917aSStefano Zampini     VecScatter sc;
1510187c917aSStefano Zampini 
1511187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1512187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
1513187c917aSStefano Zampini     ierr = VecScatterCreate(v,vl2l,vins,NULL,&sc);CHKERRQ(ierr);
1514187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1515187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1516187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1517fa23a32eSStefano Zampini   } else {
1518fa23a32eSStefano Zampini     vins = v;
1519fa23a32eSStefano Zampini   }
1520fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1521669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15229a962809SStefano Zampini 
15231ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15241ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1525a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) {
1526669cc0f4SStefano Zampini     const PetscInt    *idxs;
1527669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1528669cc0f4SStefano Zampini 
1529a040e873SStefano Zampini     idxs = shared[i];
1530a040e873SStefano Zampini     nn   = n_shared[i];
1531669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15321ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1533669cc0f4SStefano Zampini     idx  = -(idx+1);
1534669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1535669cc0f4SStefano Zampini   }
1536a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1537fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1538fa23a32eSStefano Zampini   if (vl2l) {
1539187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1540fa23a32eSStefano Zampini   }
1541669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1542669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini 
1544669cc0f4SStefano Zampini   /* assemble near null space */
1545669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1546669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1547669cc0f4SStefano Zampini   }
1548669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1549669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
15503272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
1551ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1552669cc0f4SStefano Zampini   }
1553669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1554669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1555669cc0f4SStefano Zampini }
1556669cc0f4SStefano Zampini 
15577620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15587620a527SStefano Zampini {
15597620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15607620a527SStefano Zampini   PetscErrorCode ierr;
15617620a527SStefano Zampini 
15627620a527SStefano Zampini   PetscFunctionBegin;
15637620a527SStefano Zampini   if (primalv) {
15647620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15657620a527SStefano Zampini       IS list[2], newp;
15667620a527SStefano Zampini 
15677620a527SStefano Zampini       list[0] = primalv;
15687620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15697620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
15707620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
15717620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
15727620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15737620a527SStefano Zampini     } else {
15747620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
15757620a527SStefano Zampini     }
15767620a527SStefano Zampini   }
15777620a527SStefano Zampini   PetscFunctionReturn(0);
15787620a527SStefano Zampini }
1579669cc0f4SStefano Zampini 
15801c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15811c7a958bSStefano Zampini {
15821c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15831c7a958bSStefano Zampini 
15841c7a958bSStefano Zampini   PetscFunctionBegin;
15851c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15861c7a958bSStefano Zampini   PetscFunctionReturn(0);
15871c7a958bSStefano Zampini }
1588674ae819SStefano Zampini 
15891f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15901f4df5f7SStefano Zampini {
15911f4df5f7SStefano Zampini   PetscErrorCode ierr;
15921f4df5f7SStefano Zampini   Vec            local,global;
15931f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15941f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15955c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15961f4df5f7SStefano Zampini 
15971f4df5f7SStefano Zampini   PetscFunctionBegin;
15985c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
15995c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16005c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16011f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
160221ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16031f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16046a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16056a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16066a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16076a8fc67bSStefano Zampini     }
16086a8fc67bSStefano Zampini     goto boundary;
16096a8fc67bSStefano Zampini   }
16105c5e10d6SStefano Zampini 
16111f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16121f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16131f4df5f7SStefano Zampini       PetscInt i;
16141f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16151f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16161f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16171f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16181f4df5f7SStefano Zampini       }
16191f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16201f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16211f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16221f4df5f7SStefano Zampini     }
16231f4df5f7SStefano Zampini   } else {
162421ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
162521ef3d20SStefano Zampini       DM dm;
162621ef3d20SStefano Zampini 
162721ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
162821ef3d20SStefano Zampini       if (!dm) {
162921ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
163021ef3d20SStefano Zampini       }
163121ef3d20SStefano Zampini       if (dm) {
163221ef3d20SStefano Zampini         IS      *fields;
163321ef3d20SStefano Zampini         PetscInt nf,i;
163421ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
163521ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
163621ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
163721ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
163821ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
163921ef3d20SStefano Zampini         }
164021ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
164121ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
164221ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
164321ef3d20SStefano Zampini         PetscContainer   c;
164421ef3d20SStefano Zampini 
164521ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
164621ef3d20SStefano Zampini         if (c) {
164721ef3d20SStefano Zampini           MatISLocalFields lf;
164821ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
164921ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
165021ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16511f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1652986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
165321ef3d20SStefano Zampini           if (i > 1) {
1654986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16551f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16561f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16571f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16581f4df5f7SStefano Zampini             }
16591f4df5f7SStefano Zampini           }
166021ef3d20SStefano Zampini         }
166121ef3d20SStefano Zampini       }
16627a0e7b2cSstefano_zampini     } else {
16637a0e7b2cSstefano_zampini       PetscInt i;
16647a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16657a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16667a0e7b2cSstefano_zampini       }
16671f4df5f7SStefano Zampini     }
1668986cdee1SStefano Zampini   }
16691f4df5f7SStefano Zampini 
16705c5e10d6SStefano Zampini boundary:
16711f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16721f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16737a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16747a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16751f4df5f7SStefano Zampini   }
16761f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16771f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16787a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16797a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16801f4df5f7SStefano Zampini   }
16811f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16821f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16831f4df5f7SStefano Zampini   }
16841f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16851f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16867620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16877620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16887620a527SStefano Zampini     IS        primalv = NULL;
16897620a527SStefano Zampini     PetscInt  i;
16908361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
16917a0e7b2cSstefano_zampini 
16927620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
16937620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
16947620a527SStefano Zampini     }
16957620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
16968361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
16977620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
16987620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
16997620a527SStefano Zampini   }
17007620a527SStefano Zampini   /* early stage corner detection */
17017620a527SStefano Zampini   {
17027620a527SStefano Zampini     DM dm;
17037620a527SStefano Zampini 
17047620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17057620a527SStefano Zampini     if (dm) {
17067620a527SStefano Zampini       PetscBool isda;
17077620a527SStefano Zampini 
17087620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17097620a527SStefano Zampini       if (isda) {
17107620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17117620a527SStefano Zampini         IS                     corners;
17127620a527SStefano Zampini         Mat                    lA;
17137620a527SStefano Zampini 
1714d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17157620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17167620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17177620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
1718fa55603eSStefano Zampini         if (l2l && corners) {
17197620a527SStefano Zampini           const PetscInt *idx;
17207620a527SStefano Zampini           PetscInt       bs,*idxout,n;
17217620a527SStefano Zampini 
17227620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17237620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17247620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
17257620a527SStefano Zampini           ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17267620a527SStefano Zampini           ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
17277620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1728d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17297620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17307620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17317620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17321c7a958bSStefano Zampini           pcbddc->corner_selected = PETSC_TRUE;
1733fa55603eSStefano Zampini         } else if (corners) { /* not from DMDA */
1734d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17357620a527SStefano Zampini         }
17367620a527SStefano Zampini       }
17377620a527SStefano Zampini     }
17387620a527SStefano Zampini   }
17391c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
17401c7a958bSStefano Zampini     DM dm;
17411c7a958bSStefano Zampini 
17421c7a958bSStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17431c7a958bSStefano Zampini     if (!dm) {
17441c7a958bSStefano Zampini       ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17451c7a958bSStefano Zampini     }
17461c7a958bSStefano Zampini     if (dm) {
17471c7a958bSStefano Zampini       Vec            vcoords;
17481c7a958bSStefano Zampini       PetscSection   section;
17491c7a958bSStefano Zampini       PetscReal      *coords;
17501c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
17511c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
17521c7a958bSStefano Zampini 
17531c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
17541c7a958bSStefano Zampini       ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
17551c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
17561c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
17571c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
17581c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
17591c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
17601c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
17611c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
17621c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
17631c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
17641c7a958bSStefano Zampini         PetscInt          i;
17651c7a958bSStefano Zampini         const PetscScalar *v;
17661c7a958bSStefano Zampini 
17671c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
17681c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
17691c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
17701c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
17711c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
17721c7a958bSStefano Zampini       }
17731c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
17741c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
17751c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
17761c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
17771c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
17781c7a958bSStefano Zampini     }
17791c7a958bSStefano Zampini   }
17807a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
17817a0e7b2cSstefano_zampini }
17827a0e7b2cSstefano_zampini 
17837a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
17847a0e7b2cSstefano_zampini {
17857a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
17867a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
17877a0e7b2cSstefano_zampini   IS              nis;
17887a0e7b2cSstefano_zampini   const PetscInt  *idxs;
17897a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
17907a0e7b2cSstefano_zampini   PetscBool       *ld;
17917a0e7b2cSstefano_zampini 
17927a0e7b2cSstefano_zampini   PetscFunctionBegin;
17937a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
17947a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
17957a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
17967a0e7b2cSstefano_zampini     /* init rootdata with true */
17977a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
17987a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
17997a0e7b2cSstefano_zampini   } else {
18007a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
18017a0e7b2cSstefano_zampini   }
18027a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18037a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18047a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18057a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18067a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18077a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18087a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18097a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18107a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18117a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18127a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18137a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18147a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18157a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18167a0e7b2cSstefano_zampini   } else {
18177a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18187a0e7b2cSstefano_zampini   }
18197a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18207a0e7b2cSstefano_zampini     if (ld[i])
18217a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18227a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18237a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18247a0e7b2cSstefano_zampini   *is  = nis;
18251f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18261f4df5f7SStefano Zampini }
18271f4df5f7SStefano Zampini 
18283e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18293e589ea0SStefano Zampini {
18303e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18313e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18323e589ea0SStefano Zampini   PetscErrorCode    ierr;
18333e589ea0SStefano Zampini 
18343e589ea0SStefano Zampini   PetscFunctionBegin;
18353e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18363e589ea0SStefano Zampini     PetscFunctionReturn(0);
18373e589ea0SStefano Zampini   }
18383e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18393e589ea0SStefano Zampini     Vec swap;
18403e589ea0SStefano Zampini 
18413e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18423e589ea0SStefano Zampini     swap = pcbddc->work_change;
18433e589ea0SStefano Zampini     pcbddc->work_change = r;
18443e589ea0SStefano Zampini     r = swap;
18453e589ea0SStefano Zampini   }
18463e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18473e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18483e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18493e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18503e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18513e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18523e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1853f913dca9SStefano Zampini     pcbddc->work_change = r;
18543e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18553e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18563e589ea0SStefano Zampini   }
18573e589ea0SStefano Zampini   PetscFunctionReturn(0);
18583e589ea0SStefano Zampini }
18593e589ea0SStefano Zampini 
1860a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1861a3df083aSStefano Zampini {
1862a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1863a3df083aSStefano Zampini   PetscErrorCode          ierr;
1864a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1865a3df083aSStefano Zampini 
1866a3df083aSStefano Zampini   PetscFunctionBegin;
1867a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1868a3df083aSStefano Zampini   if (transpose) {
1869a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1870a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1871a3df083aSStefano Zampini   } else {
1872a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1873a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1874a3df083aSStefano Zampini   }
1875a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1876a3df083aSStefano Zampini   if (apply_right) {
1877a3df083aSStefano Zampini     const PetscScalar *ax;
1878a3df083aSStefano Zampini     PetscInt          nl,i;
1879a3df083aSStefano Zampini 
1880a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1881a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1882a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1883a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1884a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1885a3df083aSStefano Zampini       PetscScalar    sum,val;
1886a3df083aSStefano Zampini       const PetscInt *idxs;
1887a3df083aSStefano Zampini       PetscInt       nz,j;
1888a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1889a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1890a3df083aSStefano Zampini       sum = 0.;
1891a3df083aSStefano Zampini       if (ctx->apply_p0) {
1892a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1893a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1894a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1895a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1896a3df083aSStefano Zampini         }
1897a3df083aSStefano Zampini       } else {
1898a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1899a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1900a3df083aSStefano Zampini         }
1901a3df083aSStefano Zampini       }
1902a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1903a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1904a3df083aSStefano Zampini     }
1905a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1906a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1907a3df083aSStefano Zampini   }
1908a3df083aSStefano Zampini   if (transpose) {
1909a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1910a3df083aSStefano Zampini   } else {
1911a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1912a3df083aSStefano Zampini   }
1913a3df083aSStefano Zampini   if (reset_x) {
1914a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1915a3df083aSStefano Zampini   }
1916a3df083aSStefano Zampini   if (apply_left) {
1917a3df083aSStefano Zampini     PetscScalar *ay;
1918a3df083aSStefano Zampini     PetscInt    i;
1919a3df083aSStefano Zampini 
1920a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1921a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1922a3df083aSStefano Zampini       PetscScalar    sum,val;
1923a3df083aSStefano Zampini       const PetscInt *idxs;
1924a3df083aSStefano Zampini       PetscInt       nz,j;
1925a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1926a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1927a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1928a3df083aSStefano Zampini       if (ctx->apply_p0) {
1929a3df083aSStefano Zampini         sum = 0.;
1930a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1931a3df083aSStefano Zampini           sum += ay[idxs[j]];
1932a3df083aSStefano Zampini           ay[idxs[j]] += val;
1933a3df083aSStefano Zampini         }
1934a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1935a3df083aSStefano Zampini       } else {
1936a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1937a3df083aSStefano Zampini           ay[idxs[j]] += val;
1938a3df083aSStefano Zampini         }
1939a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1940a3df083aSStefano Zampini       }
1941a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1942a3df083aSStefano Zampini     }
1943a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1944a3df083aSStefano Zampini   }
1945a3df083aSStefano Zampini   PetscFunctionReturn(0);
1946a3df083aSStefano Zampini }
1947a3df083aSStefano Zampini 
1948a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1949a3df083aSStefano Zampini {
1950a3df083aSStefano Zampini   PetscErrorCode ierr;
1951a3df083aSStefano Zampini 
1952a3df083aSStefano Zampini   PetscFunctionBegin;
1953a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1954a3df083aSStefano Zampini   PetscFunctionReturn(0);
1955a3df083aSStefano Zampini }
1956a3df083aSStefano Zampini 
1957a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1958a3df083aSStefano Zampini {
1959a3df083aSStefano Zampini   PetscErrorCode ierr;
1960a3df083aSStefano Zampini 
1961a3df083aSStefano Zampini   PetscFunctionBegin;
1962a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1963a3df083aSStefano Zampini   PetscFunctionReturn(0);
1964a3df083aSStefano Zampini }
1965a3df083aSStefano Zampini 
1966a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1967a3df083aSStefano Zampini {
1968a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1969a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1970a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1971a3df083aSStefano Zampini   PetscErrorCode          ierr;
1972a3df083aSStefano Zampini 
1973a3df083aSStefano Zampini   PetscFunctionBegin;
1974a3df083aSStefano Zampini   if (!restore) {
19751dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1976a3df083aSStefano Zampini     PetscScalar        *work;
1977b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1978a3df083aSStefano Zampini 
19799a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
19809a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1981a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1982a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1983a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1984a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1985a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1986a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1987a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1988a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1989a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1990a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1991a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1992a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1993059032f7SStefano Zampini     if (reuse) {
1994a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
19951dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1996059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1997059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1998059032f7SStefano Zampini       PetscInt               i;
1999059032f7SStefano Zampini 
2000059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2001059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2002059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2003059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2004059032f7SStefano Zampini       }
2005059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20061dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2007059032f7SStefano Zampini     }
2008a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2009a3df083aSStefano Zampini     ctx->work = work;
2010a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2011a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2012a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2013a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2014a3df083aSStefano Zampini 
2015a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2016a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2017a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2018a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2019a3df083aSStefano Zampini   } else {
20201dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20211dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20221dd7afcfSStefano Zampini     }
2023a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2024a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2025a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20261dd7afcfSStefano Zampini     ctx->A = NULL;
20271dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20281dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20291dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20301dd7afcfSStefano Zampini     if (ctx->free) {
2031059032f7SStefano Zampini       PetscInt i;
20321dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2033059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2034059032f7SStefano Zampini       }
2035059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2036059032f7SStefano Zampini     }
2037a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2038a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2039a3df083aSStefano Zampini   }
2040a3df083aSStefano Zampini   PetscFunctionReturn(0);
2041a3df083aSStefano Zampini }
2042a3df083aSStefano Zampini 
2043a3df083aSStefano Zampini /* used just in bddc debug mode */
2044a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2045a3df083aSStefano Zampini {
2046a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2047a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2048a3df083aSStefano Zampini   Mat            An;
2049a3df083aSStefano Zampini   PetscErrorCode ierr;
2050a3df083aSStefano Zampini 
2051a3df083aSStefano Zampini   PetscFunctionBegin;
2052a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2053a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2054a3df083aSStefano Zampini   if (is1) {
20557dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2056a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2057a3df083aSStefano Zampini   } else {
2058a3df083aSStefano Zampini     *B = An;
2059a3df083aSStefano Zampini   }
2060a3df083aSStefano Zampini   PetscFunctionReturn(0);
2061a3df083aSStefano Zampini }
2062a3df083aSStefano Zampini 
20631cf9b237SStefano Zampini /* TODO: add reuse flag */
20641cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20651cf9b237SStefano Zampini {
20661cf9b237SStefano Zampini   Mat            Bt;
20671cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20681cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20691cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20701cf9b237SStefano Zampini   PetscBool      flg_row;
20711cf9b237SStefano Zampini   PetscErrorCode ierr;
20721cf9b237SStefano Zampini 
20731cf9b237SStefano Zampini   PetscFunctionBegin;
20741cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20751cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20761cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20771cf9b237SStefano Zampini   nnz = n;
20781cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20791cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
20801cf9b237SStefano Zampini   }
20811cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
20821cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
20831cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
20841cf9b237SStefano Zampini   nnz = 0;
20851cf9b237SStefano Zampini   bii[0] = 0;
20861cf9b237SStefano Zampini   for (i=0;i<n;i++) {
20871cf9b237SStefano Zampini     PetscInt j;
20881cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
20891cf9b237SStefano Zampini       PetscScalar entry = a[j];
20903272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
20911cf9b237SStefano Zampini         bij[nnz] = ij[j];
20921cf9b237SStefano Zampini         bdata[nnz] = entry;
20931cf9b237SStefano Zampini         nnz++;
20941cf9b237SStefano Zampini       }
20951cf9b237SStefano Zampini     }
20961cf9b237SStefano Zampini     bii[i+1] = nnz;
20971cf9b237SStefano Zampini   }
20981cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
20991cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21001cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21011cf9b237SStefano Zampini   {
21021cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21031cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21041cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21051cf9b237SStefano Zampini   }
21063272d46bSStefano Zampini   if (*B == A) {
21073272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21083272d46bSStefano Zampini   }
21091cf9b237SStefano Zampini   *B = Bt;
21101cf9b237SStefano Zampini   PetscFunctionReturn(0);
21111cf9b237SStefano Zampini }
21121cf9b237SStefano Zampini 
21138361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21144f1b2e48SStefano Zampini {
2115c80a6c00SStefano Zampini   Mat                    B = NULL;
2116c80a6c00SStefano Zampini   DM                     dm;
21174f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21184f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21194f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2120c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21214f1b2e48SStefano Zampini   PetscInt               i,n;
21224f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2123c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21244f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21254f1b2e48SStefano Zampini 
21264f1b2e48SStefano Zampini   PetscFunctionBegin;
2127a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2128a2eca866SStefano Zampini   if (cc) *cc = NULL;
2129a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2130c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2131c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2132c80a6c00SStefano Zampini   if (!dm) {
2133c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2134c80a6c00SStefano Zampini   }
2135c80a6c00SStefano Zampini   if (dm) {
2136c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2137c80a6c00SStefano Zampini   }
21388361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
21398361f951SStefano Zampini 
2140c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2141c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2142c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2143c80a6c00SStefano Zampini     IS             cellNumbering;
2144c80a6c00SStefano Zampini     const PetscInt *cellNum;
2145c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2146c80a6c00SStefano Zampini     PetscSection   section;
2147c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2148c80a6c00SStefano Zampini     PetscSF        sfPoint;
2149c80a6c00SStefano Zampini     PetscErrorCode ierr;
2150c80a6c00SStefano Zampini 
2151c80a6c00SStefano Zampini     PetscFunctionBegin;
2152c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2153c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2154c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2155c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2156c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2157c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2158c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2159c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2160c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2161c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2162c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2163c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2164956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2165c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2166c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2167c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2168c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2169c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2170c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2171c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2172c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21735cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2174c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2175c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2176c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2177c80a6c00SStefano Zampini           *pBuf = point;
2178c80a6c00SStefano Zampini         }
2179c80a6c00SStefano Zampini       }
2180c80a6c00SStefano Zampini       n++;
2181c80a6c00SStefano Zampini     }
2182c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2183c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2184c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2185c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2186c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2187c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2188c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2189c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2190c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2191c80a6c00SStefano Zampini     }
2192c80a6c00SStefano Zampini     xadj[n] = size;
2193c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2194c80a6c00SStefano Zampini     /* Clean up */
2195c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2196c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2197c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2198c80a6c00SStefano Zampini     graph->xadj = xadj;
2199c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2200c80a6c00SStefano Zampini   } else {
2201c80a6c00SStefano Zampini     Mat       A;
22028361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2203c80a6c00SStefano Zampini 
2204c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
220563c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2206a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
220763c961adSStefano Zampini       PetscFunctionReturn(0);
220863c961adSStefano Zampini     }
22094f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22104f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22111cf9b237SStefano Zampini       PetscBool isseqdense;
22121cf9b237SStefano Zampini 
22131cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22141cf9b237SStefano Zampini       if (!isseqdense) {
22154f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22161cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22171cf9b237SStefano Zampini         PetscScalar *array;
22181cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22191cf9b237SStefano Zampini 
22201cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22211cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22221cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22231cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22241cf9b237SStefano Zampini           PetscInt j;
22251cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22261cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22271cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22281cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22291cf9b237SStefano Zampini           }
22301cf9b237SStefano Zampini         }
22311cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22329d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22331cf9b237SStefano Zampini       }
22344f1b2e48SStefano Zampini     } else {
2235c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22364f1b2e48SStefano Zampini       B = A;
22374f1b2e48SStefano Zampini     }
22384f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22394f1b2e48SStefano Zampini 
22404f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22414f1b2e48SStefano Zampini     if (filter) {
22424f1b2e48SStefano Zampini       PetscScalar *data;
22434f1b2e48SStefano Zampini       PetscInt    j,cum;
22444f1b2e48SStefano Zampini 
22454f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22464f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22474f1b2e48SStefano Zampini       cum = 0;
22484f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22494f1b2e48SStefano Zampini         PetscInt t;
22504f1b2e48SStefano Zampini 
22514f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22524f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22534f1b2e48SStefano Zampini             continue;
22544f1b2e48SStefano Zampini           }
22554f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22564f1b2e48SStefano Zampini         }
22574f1b2e48SStefano Zampini         t = xadj_filtered[i];
22584f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22594f1b2e48SStefano Zampini         cum += t;
22604f1b2e48SStefano Zampini       }
22614f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22624f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22634f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22644f1b2e48SStefano Zampini     } else {
22654f1b2e48SStefano Zampini       graph->xadj = xadj;
22664f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22674f1b2e48SStefano Zampini     }
2268c80a6c00SStefano Zampini   }
2269c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2270c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2271c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2272c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2273c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2274c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22754f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22764f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2277c80a6c00SStefano Zampini 
22784f1b2e48SStefano Zampini   /* partial clean up */
22794f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2280c80a6c00SStefano Zampini   if (B) {
2281c80a6c00SStefano Zampini     PetscBool flg_row;
22824f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22834f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
22844f1b2e48SStefano Zampini   }
2285c80a6c00SStefano Zampini   if (isplex) {
2286c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2287c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2288c80a6c00SStefano Zampini   }
22894f1b2e48SStefano Zampini 
22904f1b2e48SStefano Zampini   /* get back data */
2291c80a6c00SStefano Zampini   if (isplex) {
2292c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2293c80a6c00SStefano Zampini     if (cc || primalv) {
2294c80a6c00SStefano Zampini       Mat          A;
2295c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2296c80a6c00SStefano Zampini       PetscSection subSection;
2297c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2298c80a6c00SStefano Zampini 
2299c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2300c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2301c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2302c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2303c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2304c80a6c00SStefano Zampini 
2305c80a6c00SStefano Zampini       cids[0] = 0;
2306c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2307c80a6c00SStefano Zampini         PetscInt j;
2308c80a6c00SStefano Zampini 
2309c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2310c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2311c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2312c80a6c00SStefano Zampini 
2313c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2314c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2315c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2316c80a6c00SStefano Zampini 
2317c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2318c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2319c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2320c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2321c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2322c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2323c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2324c80a6c00SStefano Zampini               } else { /* cross-vertex */
2325c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2326c80a6c00SStefano Zampini               }
2327c80a6c00SStefano Zampini             }
2328c80a6c00SStefano Zampini           }
2329c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2330c80a6c00SStefano Zampini         }
2331c80a6c00SStefano Zampini         cids[i+1] = cum;
2332c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2333c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2334c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2335c80a6c00SStefano Zampini         }
2336c80a6c00SStefano Zampini       }
2337c80a6c00SStefano Zampini       if (cc) {
2338c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2339c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2340c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2341c80a6c00SStefano Zampini         }
2342c80a6c00SStefano Zampini         *cc = cc_n;
2343c80a6c00SStefano Zampini       }
2344c80a6c00SStefano Zampini       if (primalv) {
2345c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2346c80a6c00SStefano Zampini       }
2347c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2348c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2349c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2350c80a6c00SStefano Zampini     }
2351c80a6c00SStefano Zampini   } else {
23521cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23531cf9b237SStefano Zampini     if (cc) {
23544f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23554f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23564f1b2e48SStefano 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);
23574f1b2e48SStefano Zampini       }
23584f1b2e48SStefano Zampini       *cc = cc_n;
23591cf9b237SStefano Zampini     }
2360c80a6c00SStefano Zampini   }
23614f1b2e48SStefano Zampini   /* clean up graph */
23624f1b2e48SStefano Zampini   graph->xadj = 0;
23634f1b2e48SStefano Zampini   graph->adjncy = 0;
23644f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23654f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23664f1b2e48SStefano Zampini }
23674f1b2e48SStefano Zampini 
23685408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23695408967cSStefano Zampini {
23705408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23715408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2372dee84bffSStefano Zampini   IS             dirIS = NULL;
23734f1b2e48SStefano Zampini   PetscInt       i;
23745408967cSStefano Zampini   PetscErrorCode ierr;
23755408967cSStefano Zampini 
23765408967cSStefano Zampini   PetscFunctionBegin;
2377dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
23785408967cSStefano Zampini   if (zerodiag) {
23795408967cSStefano Zampini     Mat            A;
23805408967cSStefano Zampini     Vec            vec3_N;
23815408967cSStefano Zampini     PetscScalar    *vals;
23825408967cSStefano Zampini     const PetscInt *idxs;
2383d12d3064SStefano Zampini     PetscInt       nz,*count;
23845408967cSStefano Zampini 
23855408967cSStefano Zampini     /* p0 */
23865408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
23875408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
23885408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
23895408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
23904f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
23915408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23925408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
23935408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
23945408967cSStefano Zampini     /* v_I */
23955408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
23965408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
23975408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23985408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
23995408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24005408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24015408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24025408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24035408967cSStefano Zampini     if (dirIS) {
24045408967cSStefano Zampini       PetscInt n;
24055408967cSStefano Zampini 
24065408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24075408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24085408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24095408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24105408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24115408967cSStefano Zampini     }
24125408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24135408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24145408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24155408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2416669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24175408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24185408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24199a962809SStefano 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]));
24205408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24215408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2422d12d3064SStefano Zampini 
2423d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2424d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2425d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2426d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2427d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2428d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24299a962809SStefano 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]);
2430d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2431d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24325408967cSStefano Zampini   }
2433dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24345408967cSStefano Zampini 
24355408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24365408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24374f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24385408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24394f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24405408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2441f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2442f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
244313903a91SSatish 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);
2444f2a566d8SStefano Zampini   }
24455408967cSStefano Zampini   PetscFunctionReturn(0);
24465408967cSStefano Zampini }
24475408967cSStefano Zampini 
2448339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2449339f8db1SStefano Zampini {
2450339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24514edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2452b0f5fe93SStefano Zampini   PetscInt       nz,n;
24534edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24544edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2455339f8db1SStefano Zampini   PetscErrorCode ierr;
2456339f8db1SStefano Zampini 
2457339f8db1SStefano Zampini   PetscFunctionBegin;
24589f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24599f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2460a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2461a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2462a3df083aSStefano Zampini   }
2463a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2464a3df083aSStefano Zampini   pcbddc->benign_n = 0;
246528b8efb1Sstefano_zampini 
246628b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
24674f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
24684f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24694f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24701ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24714f1b2e48SStefano Zampini   */
24724f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
24734f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
247440fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24757fbe2174Sstefano_zampini     IS       iP = NULL;
24764f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
24774f1b2e48SStefano Zampini 
247828b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
247928b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
248028b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
248128b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
24824f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
24834f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
24844f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24854f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2486ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24877fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
24887fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
24897fbe2174Sstefano_zampini     if (iP) {
24907fbe2174Sstefano_zampini       IS newpressures;
24917fbe2174Sstefano_zampini 
24927fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
24937fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
24947fbe2174Sstefano_zampini       pressures = newpressures;
24957fbe2174Sstefano_zampini     }
249640fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
249740fa8d13SStefano Zampini     if (!sorted) {
249840fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
249940fa8d13SStefano Zampini     }
250040fa8d13SStefano Zampini   } else {
250140fa8d13SStefano Zampini     pressures = NULL;
250240fa8d13SStefano Zampini   }
250397d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
250497d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
250527b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
250697d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2507339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2508339f8db1SStefano Zampini   if (!sorted) {
2509339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2510339f8db1SStefano Zampini   }
25114edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25124edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2513339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25144f1b2e48SStefano Zampini   if (!nz) {
25154f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25164f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
251740fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
251840fa8d13SStefano Zampini   }
25194f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25204f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25214f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25224f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
25231f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25241f4df5f7SStefano Zampini   interior_dofs    = NULL;
25254edc6404Sstefano_zampini   nneu             = 0;
25264edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25274edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25284edc6404Sstefano_zampini   }
25293369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25304edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25311f4df5f7SStefano Zampini     PetscInt n,i,j;
25321f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25331f4df5f7SStefano Zampini     PetscInt *iwork;
25341f4df5f7SStefano Zampini 
25351f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25361f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25371f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25381f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
253990648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25401f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25411f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25421f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25431f4df5f7SStefano Zampini       if (!iwork[i])
25441f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25451f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25461f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25471f4df5f7SStefano Zampini   }
25484f1b2e48SStefano Zampini   if (has_null_pressures) {
25494f1b2e48SStefano Zampini     IS             *subs;
25504edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
25511f4df5f7SStefano Zampini     const PetscInt *idxs;
25521f4df5f7SStefano Zampini     PetscScalar    *array;
25531f4df5f7SStefano Zampini     Vec            *work;
25541f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25554f1b2e48SStefano Zampini 
25564f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
25574f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
25581f4df5f7SStefano 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) */
25594edc6404Sstefano_zampini     if (checkb) {
25601f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
25611f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
25621f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25631f4df5f7SStefano Zampini       /* work[0] = 1_p */
25641f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
25651f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
25661f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25671f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
25681f4df5f7SStefano Zampini       /* work[0] = 1_v */
25691f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
25701f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
25711f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
25721f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
25731f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
25741f4df5f7SStefano Zampini     }
25754f1b2e48SStefano Zampini     if (nsubs > 1) {
25764f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
25774f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
25784f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
25794f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
25804f1b2e48SStefano Zampini         PetscInt               nl;
25814f1b2e48SStefano Zampini 
25824f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
25834f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
25844f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
25854f1b2e48SStefano Zampini         if (nl) {
25864f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
25874f1b2e48SStefano Zampini 
25884edc6404Sstefano_zampini           if (checkb) {
25891f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
25901f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
25911f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
25921f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
25931f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25941f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
25951f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
25961f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
25971f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
25981f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
25991f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
26001f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
26011f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26021f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
26031f4df5f7SStefano Zampini                 break;
26041f4df5f7SStefano Zampini               }
26051f4df5f7SStefano Zampini             }
26061f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26071f4df5f7SStefano Zampini           }
26086632bad2Sstefano_zampini           if (valid && nneu) {
26096632bad2Sstefano_zampini             const PetscInt *idxs;
26101f4df5f7SStefano Zampini             PetscInt       nzb;
26111f4df5f7SStefano Zampini 
26126632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26136632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26146632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26151f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
26161f4df5f7SStefano Zampini           }
26171f4df5f7SStefano Zampini           if (valid && pressures) {
26184f1b2e48SStefano Zampini             IS t_pressure_subs;
26194f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26204f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
26214f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26224f1b2e48SStefano Zampini           }
26234f1b2e48SStefano Zampini           if (valid) {
26244f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
26254f1b2e48SStefano Zampini             pcbddc->benign_n++;
26264f1b2e48SStefano Zampini           } else {
26274f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
26284f1b2e48SStefano Zampini           }
26294f1b2e48SStefano Zampini         }
26304f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
26314f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
26324f1b2e48SStefano Zampini       }
26334f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
26344f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
26351f4df5f7SStefano Zampini 
26366632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
26371f4df5f7SStefano Zampini       if (valid && pressures) {
26384f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
26394f1b2e48SStefano Zampini       }
26404edc6404Sstefano_zampini       if (valid && checkb) {
26411f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
26421f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
26431f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26441f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
26451f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26461f4df5f7SStefano Zampini             valid = PETSC_FALSE;
26471f4df5f7SStefano Zampini             break;
26481f4df5f7SStefano Zampini           }
26491f4df5f7SStefano Zampini         }
26501f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26511f4df5f7SStefano Zampini       }
26524f1b2e48SStefano Zampini       if (valid) {
26534f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2654ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
26554f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26564f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
26574f1b2e48SStefano Zampini       }
26584f1b2e48SStefano Zampini     }
26594edc6404Sstefano_zampini     if (checkb) {
26601f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
26614f1b2e48SStefano Zampini     }
26621f4df5f7SStefano Zampini   }
26631f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
26644f1b2e48SStefano Zampini 
26654f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2666b9b0e38cSStefano Zampini     PetscInt n;
2667b9b0e38cSStefano Zampini 
26684f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26694f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2670b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2671b9b0e38cSStefano Zampini     if (n) {
26724f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
26734f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
26744f1b2e48SStefano Zampini     }
2675b9b0e38cSStefano Zampini   }
26764f1b2e48SStefano Zampini 
26774f1b2e48SStefano Zampini   /* final check for null pressures */
26784f1b2e48SStefano Zampini   if (zerodiag && pressures) {
26794f1b2e48SStefano Zampini     PetscInt nz,np;
26804f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26814f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
26824f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
26834f1b2e48SStefano Zampini   }
26844f1b2e48SStefano Zampini 
26854f1b2e48SStefano Zampini   if (recompute_zerodiag) {
26864f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26874f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
26884f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
26894f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
26904f1b2e48SStefano Zampini     } else {
26914f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
26924f1b2e48SStefano Zampini 
26934f1b2e48SStefano Zampini       nzn = 0;
26944f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26954f1b2e48SStefano Zampini         PetscInt ns;
26964f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
26974f1b2e48SStefano Zampini         nzn += ns;
26984f1b2e48SStefano Zampini       }
26994f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
27004f1b2e48SStefano Zampini       nzn = 0;
27014f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27024f1b2e48SStefano Zampini         PetscInt ns,*idxs;
27034f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27054f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
27064f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27074f1b2e48SStefano Zampini         nzn += ns;
27084f1b2e48SStefano Zampini       }
27094f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27104f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27114f1b2e48SStefano Zampini     }
27124f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27134f1b2e48SStefano Zampini   }
27144f1b2e48SStefano Zampini 
2715669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2716a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2717a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2718a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2719a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2720a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2721a198735bSStefano Zampini 
27221f4df5f7SStefano Zampini     if (pressures) {
27231f4df5f7SStefano Zampini       isused = pressures;
27241f4df5f7SStefano Zampini     } else {
27254edc6404Sstefano_zampini       isused = zerodiag_save;
27261f4df5f7SStefano Zampini     }
2727a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2728669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
27291ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
27301ae86dd6SStefano 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");
2731a198735bSStefano Zampini     n_isused = 0;
2732a198735bSStefano Zampini     if (isused) {
2733a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2734a198735bSStefano Zampini     }
2735a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2736a198735bSStefano Zampini     st = st-n_isused;
27371ae86dd6SStefano Zampini     if (n) {
2738a198735bSStefano Zampini       const PetscInt *gidxs;
2739a198735bSStefano Zampini 
27407dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2741a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2742a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2743a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2744a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2745a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
27461ae86dd6SStefano Zampini     } else {
2747a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2748a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2749a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2750a198735bSStefano Zampini     }
2751a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2752a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2753a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2754a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2755a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2756a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2757a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2758a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2759a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2760a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2761a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2762a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2763a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2764a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
27651ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27661ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27671ae86dd6SStefano Zampini   }
27684edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2769b3afcdbeSStefano Zampini 
2770b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
27714f1b2e48SStefano Zampini   if (has_null_pressures) {
27724f1b2e48SStefano Zampini     IS             zerodiagc;
27734f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
27744f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
27754f1b2e48SStefano Zampini 
27764f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2777339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2778339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2779339f8db1SStefano Zampini     /* local change of basis for pressures */
2780339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
278197d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2782339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2783339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2784339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
27854f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
27864f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
27874f1b2e48SStefano Zampini       PetscInt nzs,j;
27884f1b2e48SStefano Zampini 
27894f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
27904f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27914f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
27924f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
27934f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27944f1b2e48SStefano Zampini     }
2795339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2796339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2797339f8db1SStefano Zampini     /* set identity on velocities */
2798339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2799339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2800339f8db1SStefano Zampini     }
28014f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
28024f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
28039f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
28044f1b2e48SStefano 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);
2805339f8db1SStefano Zampini     /* set change on pressures */
28064f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28074f1b2e48SStefano Zampini       PetscScalar *array;
28084f1b2e48SStefano Zampini       PetscInt    nzs;
28094f1b2e48SStefano Zampini 
28104f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28114f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28124f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2813339f8db1SStefano Zampini         PetscScalar vals[2];
2814339f8db1SStefano Zampini         PetscInt    cols[2];
2815339f8db1SStefano Zampini 
2816339f8db1SStefano Zampini         cols[0] = idxs[i];
28174f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2818339f8db1SStefano Zampini         vals[0] = 1.;
2819b0f5fe93SStefano Zampini         vals[1] = 1.;
28204f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2821339f8db1SStefano Zampini       }
28224f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
28234f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
28244f1b2e48SStefano Zampini       array[nzs-1] = 1.;
28254f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
28264f1b2e48SStefano Zampini       /* store local idxs for p0 */
28274f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
28284f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2829339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
28304f1b2e48SStefano Zampini     }
2831339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2832339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2833a3df083aSStefano Zampini     /* project if needed */
2834a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28351dd7afcfSStefano Zampini       Mat M;
28361dd7afcfSStefano Zampini 
28371dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2838339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28391dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
28401dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2841a3df083aSStefano Zampini     }
28424f1b2e48SStefano Zampini     /* store global idxs for p0 */
28434f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2844339f8db1SStefano Zampini   }
2845ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28464f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2847b0f5fe93SStefano Zampini 
2848b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2849b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
285027b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
2851c69e9cc1SStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
285227b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2853339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2854339f8db1SStefano Zampini   PetscFunctionReturn(0);
2855339f8db1SStefano Zampini }
2856339f8db1SStefano Zampini 
2857015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2858efc2fbd9SStefano Zampini {
2859efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2860de9d7bd0SStefano Zampini   PetscScalar    *array;
2861efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2862efc2fbd9SStefano Zampini 
2863efc2fbd9SStefano Zampini   PetscFunctionBegin;
2864efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2865efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
28664f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2867efc2fbd9SStefano Zampini   }
2868de9d7bd0SStefano Zampini   if (get) {
2869efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
28704f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
28714f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2872efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2873de9d7bd0SStefano Zampini   } else {
2874de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2875de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2876de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2877de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2878efc2fbd9SStefano Zampini   }
2879efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2880efc2fbd9SStefano Zampini }
2881efc2fbd9SStefano Zampini 
2882c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2883c263805aSStefano Zampini {
2884c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2885c263805aSStefano Zampini   PetscErrorCode ierr;
2886c263805aSStefano Zampini 
2887c263805aSStefano Zampini   PetscFunctionBegin;
2888c263805aSStefano Zampini   /* TODO: add error checking
2889c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2890c263805aSStefano Zampini     - cannot push before pop.
28911c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2892c263805aSStefano Zampini   */
28934f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2894efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2895efc2fbd9SStefano Zampini   }
2896c263805aSStefano Zampini   if (pop) {
2897a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28984f1b2e48SStefano Zampini       IS       is_p0;
28994f1b2e48SStefano Zampini       MatReuse reuse;
2900c263805aSStefano Zampini 
2901c263805aSStefano Zampini       /* extract B_0 */
29024f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
29034f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
29044f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
29054f1b2e48SStefano Zampini       }
29064f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
29077dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2908c263805aSStefano Zampini       /* remove rows and cols from local problem */
2909c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
291097d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29114f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29124f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2913a3df083aSStefano Zampini     } else {
2914a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2915a3df083aSStefano Zampini       PetscScalar *vals;
2916a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2917a3df083aSStefano Zampini 
2918a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2919a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2920a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
29210b5adadeSStefano Zampini         PetscInt *nnz;
2922a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2923a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2924a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2925331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2926331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2927331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2928331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2929331e053bSStefano Zampini         }
2930331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2931331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2932331e053bSStefano Zampini       }
2933a3df083aSStefano Zampini 
2934a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2935a3df083aSStefano Zampini         PetscScalar *array;
2936a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2937a3df083aSStefano Zampini 
2938a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2939a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2940a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2941a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2942a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2943a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2944a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2945a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2946a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2947a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2948a3df083aSStefano Zampini         cum = 0;
2949a3df083aSStefano Zampini         for (j=0;j<n;j++) {
295022db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2951a3df083aSStefano Zampini             vals[cum] = array[j];
2952a3df083aSStefano Zampini             idxs_ins[cum] = j;
2953a3df083aSStefano Zampini             cum++;
2954a3df083aSStefano Zampini           }
2955a3df083aSStefano Zampini         }
2956a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2957a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2958a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2959a3df083aSStefano Zampini       }
2960a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2961a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2962a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2963a3df083aSStefano Zampini     }
2964c263805aSStefano Zampini   } else { /* push */
2965a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29664f1b2e48SStefano Zampini       PetscInt i;
29674f1b2e48SStefano Zampini 
29684f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
29694f1b2e48SStefano Zampini         PetscScalar *B0_vals;
29704f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
29714f1b2e48SStefano Zampini 
29724f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29734f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29747b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29754f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
29764f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29774f1b2e48SStefano Zampini       }
2978c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2979c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2980a3df083aSStefano Zampini     } else {
2981a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2982a3df083aSStefano Zampini     }
2983c263805aSStefano Zampini   }
2984c263805aSStefano Zampini   PetscFunctionReturn(0);
2985c263805aSStefano Zampini }
2986c263805aSStefano Zampini 
298708122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2988b1b3d7a2SStefano Zampini {
2989b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
299008122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
299108122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
299208122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
299308122e43SStefano Zampini   PetscScalar     *work,lwork;
299408122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
299508122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
2996bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
29971b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2998f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
299908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
300008122e43SStefano Zampini   PetscReal       *rwork;
300108122e43SStefano Zampini #endif
3002b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3003b1b3d7a2SStefano Zampini 
3004b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3005b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3006af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3007bd2a564bSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_symmetric)) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for this matrix pencil (herm %d, symm %d, posdef %d)",sub_schurs->is_hermitian,sub_schurs->is_symmetric,sub_schurs->is_posdef);
300806a4e24aSStefano Zampini 
3009fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3010fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3011fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3012fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30131575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3014fd14bc51SStefano Zampini   }
3015fd14bc51SStefano Zampini 
3016e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
3017e496cd5dSStefano 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);
3018e496cd5dSStefano Zampini   }
3019e496cd5dSStefano Zampini 
302008122e43SStefano Zampini   /* max size of subsets */
302108122e43SStefano Zampini   mss = 0;
302208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
302308122e43SStefano Zampini     PetscInt subset_size;
3024862806e4SStefano Zampini 
302508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
302608122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
302708122e43SStefano Zampini   }
302808122e43SStefano Zampini 
302908122e43SStefano Zampini   /* min/max and threshold */
303008122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3031f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
303208122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3033f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3034bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3035f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3036f6f667cfSStefano Zampini   }
303708122e43SStefano Zampini 
303808122e43SStefano Zampini   /* allocate lapack workspace */
303908122e43SStefano Zampini   cum = cum2 = 0;
304008122e43SStefano Zampini   maxneigs = 0;
304108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
304208122e43SStefano Zampini     PetscInt n,subset_size;
3043f6f667cfSStefano Zampini 
304408122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
304508122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
30469162d606SStefano Zampini     cum += subset_size;
30479162d606SStefano Zampini     cum2 += subset_size*n;
304808122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
304908122e43SStefano Zampini   }
305008122e43SStefano Zampini   if (mss) {
3051bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
305208122e43SStefano Zampini       PetscBLASInt B_itype = 1;
305308122e43SStefano Zampini       PetscBLASInt B_N = mss;
30544c6709b3SStefano Zampini       PetscReal    zero = 0.0;
30554c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
305608122e43SStefano Zampini 
305708122e43SStefano Zampini       B_lwork = -1;
305808122e43SStefano Zampini       S = NULL;
305908122e43SStefano Zampini       St = NULL;
3060a58a30b4SStefano Zampini       eigs = NULL;
3061a58a30b4SStefano Zampini       eigv = NULL;
3062a58a30b4SStefano Zampini       B_iwork = NULL;
3063a58a30b4SStefano Zampini       B_ifail = NULL;
3064d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3065d1710679SStefano Zampini       rwork = NULL;
3066d1710679SStefano Zampini #endif
30678bec7fa6SStefano Zampini       thresh = 1.0;
306808122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
306908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
307008122e43SStefano 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));
307108122e43SStefano Zampini #else
307208122e43SStefano 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));
307308122e43SStefano Zampini #endif
307408122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
307508122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3076bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
307708122e43SStefano Zampini   } else {
307808122e43SStefano Zampini     lwork = 0;
307908122e43SStefano Zampini   }
308008122e43SStefano Zampini 
308108122e43SStefano Zampini   nv = 0;
3082d62866d3SStefano 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) */
3083d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
308408122e43SStefano Zampini   }
30854c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3086f6f667cfSStefano Zampini   if (allocated_S_St) {
3087f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3088f6f667cfSStefano Zampini   }
3089f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
309008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
309108122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
309208122e43SStefano Zampini #endif
30939162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
30949162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
30959162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
309608122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
30979162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
309808122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
309908122e43SStefano Zampini 
310008122e43SStefano Zampini   maxneigs = 0;
310172b8c272SStefano Zampini   cum = cumarray = 0;
31029162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
31039162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3104d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
310508122e43SStefano Zampini     const PetscInt *idxs;
310608122e43SStefano Zampini 
3107d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
310808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
310908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
311008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
311108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31129162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31139162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
311408122e43SStefano Zampini     }
3115d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
311608122e43SStefano Zampini   }
311708122e43SStefano Zampini 
311808122e43SStefano Zampini   if (mss) { /* multilevel */
311908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
312008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
312108122e43SStefano Zampini   }
312208122e43SStefano Zampini 
3123bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3124bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
312508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
312608122e43SStefano Zampini     const PetscInt *idxs;
31279d54b7f4SStefano Zampini     PetscReal      upper,lower;
3128862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
312908122e43SStefano Zampini     PetscBLASInt   B_N;
3130aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3131bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
313208122e43SStefano Zampini 
31339d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
31349d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3135bd2a564bSStefano Zampini       lower = uthresh;
31369d54b7f4SStefano Zampini     } else {
3137bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3138bd2a564bSStefano Zampini       upper = 1./uthresh;
31399d54b7f4SStefano Zampini       lower = 0.;
31409d54b7f4SStefano Zampini     }
3141862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3142ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3143f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3144bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3145bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3146bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3147bd2a564bSStefano Zampini       Mat T;
3148bd2a564bSStefano Zampini 
3149bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3150bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3151bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3152bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3153bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3154bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3155bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3156bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3157bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3158bd2a564bSStefano Zampini             PetscInt       nz,k;
3159bd2a564bSStefano Zampini             const PetscInt *idxs;
3160bd2a564bSStefano Zampini 
3161bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3162bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3163bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3164bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3165bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3166bd2a564bSStefano Zampini             }
3167bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3168bd2a564bSStefano Zampini           }
3169bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3170bd2a564bSStefano Zampini           break;
3171bd2a564bSStefano Zampini         }
3172bd2a564bSStefano Zampini       }
3173bd2a564bSStefano Zampini     }
3174bd2a564bSStefano Zampini 
3175f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3176bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3177aff50787SStefano Zampini         PetscInt j,k;
3178aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3179aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3180aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
318108122e43SStefano Zampini         }
318208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3183aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3184aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3185aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3186aff50787SStefano Zampini           }
318708122e43SStefano Zampini         }
318808122e43SStefano Zampini       } else {
318908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
319008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
319108122e43SStefano Zampini       }
31928bec7fa6SStefano Zampini     } else {
3193f6f667cfSStefano Zampini       S = Sarray + cumarray;
3194f6f667cfSStefano Zampini       St = Starray + cumarray;
31958bec7fa6SStefano Zampini     }
3196aff50787SStefano Zampini     /* see if we can save some work */
3197b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3198aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3199aff50787SStefano Zampini     }
3200aff50787SStefano Zampini 
3201b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3202aff50787SStefano Zampini       B_neigs = 0;
3203aff50787SStefano Zampini     } else {
3204bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
320508122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3206f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
32074c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
32089552c7c7SStefano Zampini         PetscInt     nmin_s;
3209bd2a564bSStefano Zampini         PetscBool    compute_range;
3210bd2a564bSStefano Zampini 
32119036ceccSStefano Zampini         B_neigs = 0;
3212bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3213bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
321408122e43SStefano Zampini 
3215fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
32169036ceccSStefano Zampini           PetscInt nc = 0;
3217d16cbb6bSStefano Zampini 
32189036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
32199036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
32209036ceccSStefano Zampini           }
32219036ceccSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d size %d count %d fid %d (range %d) (change %d).\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]+1,pcbddc->mat_graph->which_dof[idxs[0]],compute_range,nc);CHKERRQ(ierr);
3222b7ab4a40SStefano Zampini         }
3223b7ab4a40SStefano Zampini 
322408122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3225b7ab4a40SStefano Zampini         if (compute_range) {
3226d16cbb6bSStefano Zampini 
3227d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3228bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
322908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32309d54b7f4SStefano 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));
323108122e43SStefano Zampini #else
32329d54b7f4SStefano 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));
323308122e43SStefano Zampini #endif
3234bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
32359036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3236bd2a564bSStefano Zampini             PetscReal bb[2];
3237bd2a564bSStefano Zampini 
3238bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3239bd2a564bSStefano Zampini             switch (recipe) {
3240bd2a564bSStefano Zampini             case 0:
3241bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3242bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3243bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3244bd2a564bSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
3245bd2a564bSStefano Zampini #else
3246bd2a564bSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
3247bd2a564bSStefano Zampini #endif
3248bd2a564bSStefano Zampini               break;
3249bd2a564bSStefano Zampini             case 1:
3250bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3251bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3252bd2a564bSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
3253bd2a564bSStefano Zampini #else
3254bd2a564bSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
3255bd2a564bSStefano Zampini #endif
3256bd2a564bSStefano Zampini               if (!scal) {
32579036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3258bd2a564bSStefano Zampini 
3259aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3260bd2a564bSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3261bd2a564bSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3262bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3263bd2a564bSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
3264bd2a564bSStefano Zampini #else
3265bd2a564bSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
3266bd2a564bSStefano Zampini #endif
3267bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3268bd2a564bSStefano Zampini               }
3269bd2a564bSStefano Zampini               break;
32709036ceccSStefano Zampini             case 2:
32719036ceccSStefano Zampini               if (scal) {
32729036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
32739036ceccSStefano Zampini                 bb[1] = 0;
32749036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
32759036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
32769036ceccSStefano Zampini #else
32779036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
32789036ceccSStefano Zampini #endif
32799036ceccSStefano Zampini               } else {
32809036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
32819036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
32829036ceccSStefano Zampini 
32839036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
32849036ceccSStefano Zampini                 if (lthresh > 0.0) {
32859036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
32869036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
32879036ceccSStefano Zampini 
32889036ceccSStefano Zampini                   import = PETSC_TRUE;
32899036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
32909036ceccSStefano Zampini                   PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
32919036ceccSStefano Zampini #else
32929036ceccSStefano Zampini                   PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
32939036ceccSStefano Zampini #endif
32949036ceccSStefano Zampini                 }
32959036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
32969036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
32979036ceccSStefano Zampini                 if (import) {
32989036ceccSStefano Zampini                   ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
32999036ceccSStefano Zampini                   ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33009036ceccSStefano Zampini                 }
33019036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33029036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
33039036ceccSStefano Zampini #else
33049036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
33059036ceccSStefano Zampini #endif
33069036ceccSStefano Zampini                 B_neigs += B_neigs2;
33079036ceccSStefano Zampini               }
33089036ceccSStefano Zampini               break;
33099036ceccSStefano Zampini             case 3:
33109036ceccSStefano Zampini               if (scal) {
33119036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
33129036ceccSStefano Zampini               } else {
33139036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
33149036ceccSStefano Zampini               }
33159036ceccSStefano Zampini               if (!scal) {
33169036ceccSStefano Zampini                 bb[0] = uthresh;
33179036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
33189036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33199036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
33209036ceccSStefano Zampini #else
33219036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
33229036ceccSStefano Zampini #endif
33239036ceccSStefano Zampini               }
33249036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
33259036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
33269036ceccSStefano Zampini 
33279036ceccSStefano Zampini                 B_IL = 1;
33289036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
33299036ceccSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33309036ceccSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33319036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33329036ceccSStefano 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*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
33339036ceccSStefano Zampini #else
33349036ceccSStefano 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*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
33359036ceccSStefano Zampini #endif
33369036ceccSStefano Zampini                 B_neigs += B_neigs2;
33379036ceccSStefano Zampini               }
33389036ceccSStefano Zampini               break;
333948cebe81SStefano Zampini             case 4:
334048cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
334148cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
334248cebe81SStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
334348cebe81SStefano Zampini #else
334448cebe81SStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
334548cebe81SStefano Zampini #endif
334648cebe81SStefano Zampini               {
334748cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
334848cebe81SStefano Zampini 
334948cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
335048cebe81SStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
335148cebe81SStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
335248cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
335348cebe81SStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
335448cebe81SStefano Zampini #else
335548cebe81SStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
335648cebe81SStefano Zampini #endif
335748cebe81SStefano Zampini                 B_neigs += B_neigs2;
335848cebe81SStefano Zampini               }
335948cebe81SStefano Zampini               break;
336080db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
336180db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
336280db8efeSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
336380db8efeSStefano Zampini #else
336480db8efeSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
336580db8efeSStefano Zampini #endif
336680db8efeSStefano Zampini               {
336780db8efeSStefano Zampini                 PetscInt e,k,ne;
336880db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
336980db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
337080db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
337180db8efeSStefano Zampini                     eigs[ne] = eigs[e];
337280db8efeSStefano Zampini                     ne++;
337380db8efeSStefano Zampini                   }
337480db8efeSStefano Zampini                 }
337580db8efeSStefano Zampini                 ierr = PetscMemcpy(eigv,S,B_N*ne*sizeof(PetscScalar));CHKERRQ(ierr);
337680db8efeSStefano Zampini                 B_neigs = ne;
337780db8efeSStefano Zampini               }
337880db8efeSStefano Zampini               break;
3379bd2a564bSStefano Zampini             default:
3380bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3381bd2a564bSStefano Zampini               break;
3382bd2a564bSStefano Zampini             }
3383bd2a564bSStefano Zampini           }
3384bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3385d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3386d16cbb6bSStefano Zampini           B_IL = 1;
3387d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33889d54b7f4SStefano 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));
3389d16cbb6bSStefano Zampini #else
33909d54b7f4SStefano 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));
3391d16cbb6bSStefano Zampini #endif
3392b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3393b7ab4a40SStefano Zampini           PetscInt k;
3394b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3395b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3396b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3397b7ab4a40SStefano Zampini           nmin = nmax;
3398b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3399b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3400b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3401b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3402b7ab4a40SStefano Zampini           }
3403d16cbb6bSStefano Zampini         }
340408122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
340508122e43SStefano Zampini         if (B_ierr) {
34066c4ed002SBarry 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);
34076c4ed002SBarry 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);
34086c4ed002SBarry 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);
340908122e43SStefano Zampini         }
341008122e43SStefano Zampini 
341108122e43SStefano Zampini         if (B_neigs > nmax) {
3412fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3413bd2a564bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);CHKERRQ(ierr);
3414fd14bc51SStefano Zampini           }
3415bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
341608122e43SStefano Zampini           B_neigs = nmax;
341708122e43SStefano Zampini         }
341808122e43SStefano Zampini 
34199552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
34209552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
34219036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
342208122e43SStefano Zampini 
34239d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3424bd2a564bSStefano Zampini             if (scal) {
3425bd2a564bSStefano Zampini               B_IU = nmin_s;
3426bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3427bd2a564bSStefano Zampini             } else {
3428f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
34299d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3430bd2a564bSStefano Zampini             }
34319d54b7f4SStefano Zampini           } else {
34329d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
34339d54b7f4SStefano Zampini             B_IU = nmin_s;
34349d54b7f4SStefano Zampini           }
3435fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3436fd14bc51SStefano 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);
3437fd14bc51SStefano Zampini           }
3438bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
34391ae86dd6SStefano Zampini             PetscInt j,k;
344008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
34411ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
34421ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
34431ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
344408122e43SStefano Zampini               }
344508122e43SStefano Zampini             }
344608122e43SStefano Zampini           } else {
344708122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
344808122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
344908122e43SStefano Zampini           }
345008122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
345108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
34529d54b7f4SStefano 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));
345308122e43SStefano Zampini #else
34549d54b7f4SStefano 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));
345508122e43SStefano Zampini #endif
345608122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
345708122e43SStefano Zampini           B_neigs += B_neigs2;
345808122e43SStefano Zampini         }
345908122e43SStefano Zampini         if (B_ierr) {
34606c4ed002SBarry 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);
34616c4ed002SBarry 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);
34626c4ed002SBarry 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);
346308122e43SStefano Zampini         }
3464fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3465ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
346608122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
346708122e43SStefano Zampini             if (eigs[j] == 0.0) {
3468ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
346908122e43SStefano Zampini             } else {
34709d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3471ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
34729d54b7f4SStefano Zampini               } else {
34739d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
34749d54b7f4SStefano Zampini               }
3475fd14bc51SStefano Zampini             }
347608122e43SStefano Zampini           }
347708122e43SStefano Zampini         }
3478bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3479aff50787SStefano Zampini     }
34806c3e6151SStefano Zampini     /* change the basis back to the original one */
34816c3e6151SStefano Zampini     if (sub_schurs->change) {
348272b8c272SStefano Zampini       Mat change,phi,phit;
34836c3e6151SStefano Zampini 
348403dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
34856c3e6151SStefano Zampini         PetscInt ii;
34866c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
34876c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
34886c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3489684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3490684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3491684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3492684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3493684229deSStefano Zampini #else
34946c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3495684229deSStefano Zampini #endif
34966c3e6151SStefano Zampini           }
34976c3e6151SStefano Zampini         }
34986c3e6151SStefano Zampini       }
349972b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
35006c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
350172b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
35026c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
35036c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
35046c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
35056c3e6151SStefano Zampini     }
35068bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
35078bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
35089162d606SStefano Zampini     if (B_neigs) {
35099162d606SStefano 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);
3510fd14bc51SStefano Zampini 
3511fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
35129552c7c7SStefano Zampini         PetscInt ii;
35139552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3514ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
35159552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3516ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3517ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3518ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3519ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3520ac47001eSStefano Zampini #else
3521ac47001eSStefano 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);
3522ac47001eSStefano Zampini #endif
35239552c7c7SStefano Zampini           }
35249552c7c7SStefano Zampini         }
3525fd14bc51SStefano Zampini       }
35269162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
35279162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
35289162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
35299162d606SStefano Zampini       cum++;
353008122e43SStefano Zampini     }
353108122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
353208122e43SStefano Zampini     /* shift for next computation */
353308122e43SStefano Zampini     cumarray += subset_size*subset_size;
353408122e43SStefano Zampini   }
3535fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3536fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3537fd14bc51SStefano Zampini   }
353808122e43SStefano Zampini 
353908122e43SStefano Zampini   if (mss) {
354008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
354108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3542f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3543f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3544f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
354508122e43SStefano Zampini   }
3546f6f667cfSStefano Zampini   if (allocated_S_St) {
3547f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3548f6f667cfSStefano Zampini   }
3549f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
355008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
355108122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
355208122e43SStefano Zampini #endif
355308122e43SStefano Zampini   if (pcbddc->dbg_flag) {
35541b968477SStefano Zampini     PetscInt maxneigs_r;
3555b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
35569b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
355708122e43SStefano Zampini   }
355808122e43SStefano Zampini   PetscFunctionReturn(0);
355908122e43SStefano Zampini }
3560b1b3d7a2SStefano Zampini 
3561c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3562c8587f34SStefano Zampini {
35638629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3564c8587f34SStefano Zampini   PetscErrorCode ierr;
3565c8587f34SStefano Zampini 
3566c8587f34SStefano Zampini   PetscFunctionBegin;
3567f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
35685e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3569c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3570c8587f34SStefano Zampini 
3571684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
35720fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3573684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3574c8587f34SStefano Zampini 
35758629588bSStefano Zampini   /*
35768629588bSStefano Zampini      Setup local correction and local part of coarse basis.
35778629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
35788629588bSStefano Zampini   */
357947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
35808629588bSStefano Zampini 
35818629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
35828629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
35838629588bSStefano Zampini 
35848629588bSStefano Zampini   /* free */
35858629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3586c8587f34SStefano Zampini   PetscFunctionReturn(0);
3587c8587f34SStefano Zampini }
3588c8587f34SStefano Zampini 
3589674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3590674ae819SStefano Zampini {
3591674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3592674ae819SStefano Zampini   PetscErrorCode ierr;
3593674ae819SStefano Zampini 
3594674ae819SStefano Zampini   PetscFunctionBegin;
3595674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
359630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3597674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3598785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3599674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3600f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3601f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3602785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
360363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
360463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3605674ae819SStefano Zampini   PetscFunctionReturn(0);
3606674ae819SStefano Zampini }
3607674ae819SStefano Zampini 
3608674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3609674ae819SStefano Zampini {
3610674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
36114f1b2e48SStefano Zampini   PetscInt       i;
3612674ae819SStefano Zampini   PetscErrorCode ierr;
3613674ae819SStefano Zampini 
3614674ae819SStefano Zampini   PetscFunctionBegin;
36151e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
36161e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3617a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3618b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3619674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
362016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
36211dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3622674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3623669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3624fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
36259326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
36264f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
36274f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
36284f1b2e48SStefano Zampini   }
3629e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
36304f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3631e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3632c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
36338af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
36341c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3635674ae819SStefano Zampini   PetscFunctionReturn(0);
3636674ae819SStefano Zampini }
3637674ae819SStefano Zampini 
3638674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3639674ae819SStefano Zampini {
3640674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3641674ae819SStefano Zampini   PetscErrorCode ierr;
3642674ae819SStefano Zampini 
3643674ae819SStefano Zampini   PetscFunctionBegin;
3644674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
364558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3646ca92afb2SStefano Zampini     PetscScalar *array;
364706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
364806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
364958da7f69SStefano Zampini   }
3650674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3651674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
365215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
365315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3654674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3655674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3656674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
365706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3658674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3659674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
36608ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3661674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3662674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3663674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
36649326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
36659326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
36669326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3667f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3668727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
36690e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3670f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
367170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
367281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
36730369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
36741dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
36754f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
36768b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3677ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3678ca92afb2SStefano Zampini     PetscInt i;
3679ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3680ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3681ca92afb2SStefano Zampini     }
3682ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3683ca92afb2SStefano Zampini   }
36844f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3685674ae819SStefano Zampini   PetscFunctionReturn(0);
3686674ae819SStefano Zampini }
3687674ae819SStefano Zampini 
3688f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
36896bfb1811SStefano Zampini {
36906bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
36916bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
36926bfb1811SStefano Zampini   VecType        impVecType;
36934f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
36946bfb1811SStefano Zampini   PetscErrorCode ierr;
36956bfb1811SStefano Zampini 
36966bfb1811SStefano Zampini   PetscFunctionBegin;
36974f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3698b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
36996bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3700e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3701e7b262bdSStefano Zampini   /* R nodes */
3702e7b262bdSStefano Zampini   old_size = -1;
3703e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3704e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3705e7b262bdSStefano Zampini   }
3706e7b262bdSStefano Zampini   if (n_R != old_size) {
3707e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3708e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
37096bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
37106bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
37116bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
37126bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3713e7b262bdSStefano Zampini   }
3714e7b262bdSStefano Zampini   /* local primal dofs */
3715e7b262bdSStefano Zampini   old_size = -1;
3716e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3717e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3718e7b262bdSStefano Zampini   }
3719e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3720e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
372183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3722e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
37236bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3724e7b262bdSStefano Zampini   }
3725e7b262bdSStefano Zampini   /* local explicit constraints */
3726e7b262bdSStefano Zampini   old_size = -1;
3727e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3728e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3729e7b262bdSStefano Zampini   }
3730e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3731e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
373283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
373383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
373483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
373583b7ccabSStefano Zampini   }
37366bfb1811SStefano Zampini   PetscFunctionReturn(0);
37376bfb1811SStefano Zampini }
37386bfb1811SStefano Zampini 
373947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
374088ebb749SStefano Zampini {
374125084f0cSStefano Zampini   PetscErrorCode  ierr;
374225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
374388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
374488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3745d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
374625084f0cSStefano Zampini   /* submatrices of local problem */
374780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
374806656605SStefano Zampini   /* submatrices of local coarse problem */
374906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
375025084f0cSStefano Zampini   /* working matrices */
375106656605SStefano Zampini   Mat             C_CR;
375225084f0cSStefano Zampini   /* additional working stuff */
375306656605SStefano Zampini   PC              pc_R;
3754c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
37555cbda25cSStefano Zampini   Vec             dummy_vec;
3756c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
375725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
375806656605SStefano Zampini   PetscScalar     *work;
375906656605SStefano Zampini   PetscInt        *idx_V_B;
3760ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
376106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3762ffd830a3SStefano Zampini 
376325084f0cSStefano Zampini   /* some shortcuts to scalars */
376406656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
376588ebb749SStefano Zampini 
376688ebb749SStefano Zampini   PetscFunctionBegin;
37679a962809SStefano 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");
3768ffd830a3SStefano Zampini 
3769ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3770b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
37714f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3772b371cd4fSStefano Zampini   n_B = pcis->n_B;
3773b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
377488ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
377588ebb749SStefano Zampini 
377688ebb749SStefano Zampini   /* vertices in boundary numbering */
3777785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
37780e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
37796c4ed002SBarry 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);
378088ebb749SStefano Zampini 
378106656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3782019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
378306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
378406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
378506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
378606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
378706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
378806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
378906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
379006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
379106656605SStefano Zampini 
379206656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
379306656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
37942958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
379506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
379606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
379706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3798ffd830a3SStefano Zampini   lda_rhs = n_R;
3799a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
380006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
380106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3802b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3803df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3804d62866d3SStefano Zampini     MatFactorType      type;
3805d62866d3SStefano Zampini 
3806df4d28bfSStefano Zampini     F = reuse_solver->F;
38076816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3808d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3809ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
381022db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
381106656605SStefano Zampini   } else {
381206656605SStefano Zampini     F = NULL;
381306656605SStefano Zampini   }
381406656605SStefano Zampini 
3815c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3816c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3817c58f9fdbSStefano Zampini   if (F) {
3818ea799195SBarry Smith     MatSolverType solver;
3819c58f9fdbSStefano Zampini 
38203ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3821c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3822c58f9fdbSStefano Zampini   }
3823c58f9fdbSStefano Zampini 
3824ffd830a3SStefano Zampini   /* allocate workspace */
3825ffd830a3SStefano Zampini   n = 0;
3826ffd830a3SStefano Zampini   if (n_constraints) {
3827ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3828ffd830a3SStefano Zampini   }
3829ffd830a3SStefano Zampini   if (n_vertices) {
3830ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3831ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3832ffd830a3SStefano Zampini   }
38332a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
38342a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
38352a3a6641Sstefano_zampini   }
3836ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3837ffd830a3SStefano Zampini 
38385cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
38395cbda25cSStefano Zampini   dummy_vec = NULL;
38405cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
38415cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
38425cbda25cSStefano Zampini   }
38435cbda25cSStefano Zampini 
384488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
384588ebb749SStefano Zampini   if (n_constraints) {
3846837cedc9SStefano Zampini     Mat         M3,C_B;
384706656605SStefano Zampini     IS          is_aux;
384880677318SStefano Zampini     PetscScalar *array,*array2;
384906656605SStefano Zampini 
3850f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
385180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
385288ebb749SStefano Zampini 
385325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
385425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
38557dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
38567dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
385788ebb749SStefano Zampini 
385880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
385980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3860c58f9fdbSStefano Zampini     if (!sparserhs) {
3861ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
386288ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
386306656605SStefano Zampini         const PetscScalar *row_cmat_values;
386406656605SStefano Zampini         const PetscInt    *row_cmat_indices;
386506656605SStefano Zampini         PetscInt          size_of_constraint,j;
386688ebb749SStefano Zampini 
386706656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
386806656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3869ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
387006656605SStefano Zampini         }
387106656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
387206656605SStefano Zampini       }
3873c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3874c58f9fdbSStefano Zampini     } else {
3875c58f9fdbSStefano Zampini       Mat tC_CR;
3876c58f9fdbSStefano Zampini 
3877c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3878c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3879c58f9fdbSStefano Zampini         PetscScalar *aa;
3880c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3881c58f9fdbSStefano Zampini         PetscBool   done;
3882c58f9fdbSStefano Zampini 
3883c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
388413903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3885c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3886c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3887c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
388813903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3889c58f9fdbSStefano Zampini       } else {
3890c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3891c58f9fdbSStefano Zampini         tC_CR = C_CR;
3892c58f9fdbSStefano Zampini       }
3893c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3894c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3895c58f9fdbSStefano Zampini     }
3896ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
389706656605SStefano Zampini     if (F) {
3898a3df083aSStefano Zampini       if (need_benign_correction) {
3899df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3900a3df083aSStefano Zampini 
390172b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
390272b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3903a3df083aSStefano Zampini       }
3904c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3905a3df083aSStefano Zampini       if (need_benign_correction) {
3906a3df083aSStefano Zampini         PetscScalar        *marr;
3907df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3908a3df083aSStefano Zampini 
3909a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
39105cbda25cSStefano Zampini         if (lda_rhs != n_R) {
39115cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
39125cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
39135cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
39145cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
39155cbda25cSStefano Zampini           }
39165cbda25cSStefano Zampini         } else {
3917a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3918a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
39195cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3920a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3921a3df083aSStefano Zampini           }
39225cbda25cSStefano Zampini         }
3923a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3924a3df083aSStefano Zampini       }
392506656605SStefano Zampini     } else {
392680677318SStefano Zampini       PetscScalar *marr;
392780677318SStefano Zampini 
392880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
392906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3930ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3931ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
393206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
393306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
393406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
393506656605SStefano Zampini       }
393680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
393706656605SStefano Zampini     }
3938c58f9fdbSStefano Zampini     if (sparserhs) {
3939c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3940c58f9fdbSStefano Zampini     }
3941c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
394280677318SStefano Zampini     if (!pcbddc->switch_static) {
394380677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
394480677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
394580677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
394680677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3947ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
394880677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
394980677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
395080677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
395180677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
395280677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
395380677318SStefano Zampini       }
395480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
395580677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
395672b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
395780677318SStefano Zampini     } else {
3958ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3959ffd830a3SStefano Zampini         IS dummy;
3960ffd830a3SStefano Zampini 
3961ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
39627dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3963ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3964ffd830a3SStefano Zampini       } else {
396580677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
396680677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3967ffd830a3SStefano Zampini       }
396825084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
396980677318SStefano Zampini     }
397080677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
397180677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
397280677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
397380677318SStefano Zampini     if (isCHOL) {
397480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
397580677318SStefano Zampini     } else {
397625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
397780677318SStefano Zampini     }
3978837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
397980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
3980837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
398172b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
3982837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
3983837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
3984f4ddd8eeSStefano Zampini   }
3985fc227af8SStefano Zampini 
3986fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
398788ebb749SStefano Zampini   if (n_vertices) {
398806656605SStefano Zampini     IS        is_aux;
3989c58f9fdbSStefano Zampini     PetscBool isseqaij;
39903a50541eSStefano Zampini 
3991b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
39926816873aSStefano Zampini       IS tis;
39936816873aSStefano Zampini 
39946816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
39956816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
39966816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
39976816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
39986816873aSStefano Zampini     } else {
39993a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
40006816873aSStefano Zampini     }
40017dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
40027dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
4003c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
4004c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
4005c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4006c58f9fdbSStefano Zampini     }
40077dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
400825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
400988ebb749SStefano Zampini   }
401088ebb749SStefano Zampini 
401188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4012f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
401306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
401406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
401506656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
401606656605SStefano Zampini     }
4017f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
401806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
401906656605SStefano Zampini       PetscScalar *marray;
402006656605SStefano Zampini 
402106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
402206656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4023f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4024f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4025f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4026f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4027f4ddd8eeSStefano Zampini     }
4028f4ddd8eeSStefano Zampini   }
402906656605SStefano Zampini 
4030f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4031a6e023c1Sstefano_zampini     PetscScalar *marr;
403288ebb749SStefano Zampini 
4033a6e023c1Sstefano_zampini     /* memory size */
403406656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4035a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4036a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4037a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4038a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4039a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
40408eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4041a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4042a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
404388ebb749SStefano Zampini     }
40443301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4045a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4046a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
40478eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4048a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
404988ebb749SStefano Zampini       }
405088ebb749SStefano Zampini     } else {
4051c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4052c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
40531b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4054c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4055c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4056c0553b1fSStefano Zampini       }
405788ebb749SStefano Zampini     }
405806656605SStefano Zampini   }
4059019a44ceSStefano Zampini 
406006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
40614f1b2e48SStefano Zampini   p0_lidx_I = NULL;
40624f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4063d12edf2fSStefano Zampini     const PetscInt *idxs;
4064d12edf2fSStefano Zampini 
4065d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
40664f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
40674f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
40684f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
40694f1b2e48SStefano Zampini     }
4070d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4071d12edf2fSStefano Zampini   }
4072d16cbb6bSStefano Zampini 
407306656605SStefano Zampini   /* vertices */
407406656605SStefano Zampini   if (n_vertices) {
4075c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
407616f15bc4SStefano Zampini 
4077af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
407804708bb6SStefano Zampini 
407916f15bc4SStefano Zampini     if (n_R) {
408014393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
408106656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
408216f15bc4SStefano Zampini       PetscScalar  *x,*y;
408306656605SStefano Zampini 
408421eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
408514393ed6SStefano Zampini       if (need_benign_correction) {
408614393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
408714393ed6SStefano Zampini         IS                     is_p0;
408814393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
408914393ed6SStefano Zampini 
409014393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
409114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
409214393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
4093af25d912SStefano 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);
409414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
409514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
40967dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
409714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
409814393ed6SStefano Zampini       }
409914393ed6SStefano Zampini 
4100c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4101c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4102ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4103af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4104ffd830a3SStefano Zampini         } else {
4105ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4106ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4107ca92afb2SStefano Zampini           PetscInt       n;
4108ca92afb2SStefano Zampini           PetscBool      flg_row;
4109ffd830a3SStefano Zampini 
4110ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4111ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
41129d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4113ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4114ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4115ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4116ca92afb2SStefano Zampini             PetscInt j;
4117ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4118ffd830a3SStefano Zampini           }
4119ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4120ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4121ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4122ffd830a3SStefano Zampini         }
4123a3df083aSStefano Zampini         if (need_benign_correction) {
4124df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4125a3df083aSStefano Zampini           PetscScalar        *marr;
4126a3df083aSStefano Zampini 
4127a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
412814393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
412914393ed6SStefano Zampini 
413014393ed6SStefano Zampini                  | 0 0  0 | (V)
413114393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
413214393ed6SStefano Zampini                  | 0 0 -1 | (p0)
413314393ed6SStefano Zampini 
413414393ed6SStefano Zampini           */
4135df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
413614393ed6SStefano Zampini             const PetscScalar *vals;
413714393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
413814393ed6SStefano Zampini             PetscInt          n,j,nz;
413914393ed6SStefano Zampini 
4140df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4141df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
414214393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
414314393ed6SStefano Zampini             for (j=0;j<n;j++) {
414414393ed6SStefano Zampini               PetscScalar val = vals[j];
414514393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
414614393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
414714393ed6SStefano Zampini             }
414814393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4149df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
415014393ed6SStefano Zampini           }
415172b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
415272b8c272SStefano Zampini         }
4153c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4154c58f9fdbSStefano Zampini         Brhs = A_RV;
4155c58f9fdbSStefano Zampini       } else {
4156c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4157c58f9fdbSStefano Zampini 
4158c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4159fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4160c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4161c58f9fdbSStefano Zampini         } else {
4162c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4163c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4164c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4165c58f9fdbSStefano Zampini           A_RVT = A_VR;
4166c58f9fdbSStefano Zampini         }
4167c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4168c58f9fdbSStefano Zampini           PetscScalar *aa;
4169c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4170c58f9fdbSStefano Zampini           PetscBool   done;
4171c58f9fdbSStefano Zampini 
4172c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
417313903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4174c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4175c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4176c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
417713903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4178c58f9fdbSStefano Zampini         } else {
4179c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4180c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4181c58f9fdbSStefano Zampini         }
4182c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4183c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4184c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4185c58f9fdbSStefano Zampini       }
418672b8c272SStefano Zampini       if (F) {
418714393ed6SStefano Zampini         /* need to correct the rhs */
418872b8c272SStefano Zampini         if (need_benign_correction) {
418972b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
419072b8c272SStefano Zampini           PetscScalar        *marr;
419172b8c272SStefano Zampini 
4192c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
41935cbda25cSStefano Zampini           if (lda_rhs != n_R) {
41945cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
41955cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
41965cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
41975cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
41985cbda25cSStefano Zampini             }
41995cbda25cSStefano Zampini           } else {
4200a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4201a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
42025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4203a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4204a3df083aSStefano Zampini             }
42055cbda25cSStefano Zampini           }
4206c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4207a3df083aSStefano Zampini         }
4208c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4209c58f9fdbSStefano Zampini         if (restoreavr) {
4210c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4211c58f9fdbSStefano Zampini         }
421214393ed6SStefano Zampini         /* need to correct the solution */
4213a3df083aSStefano Zampini         if (need_benign_correction) {
4214df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4215a3df083aSStefano Zampini           PetscScalar        *marr;
4216a3df083aSStefano Zampini 
4217a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
42185cbda25cSStefano Zampini           if (lda_rhs != n_R) {
42195cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
42205cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
42215cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
42225cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
42235cbda25cSStefano Zampini             }
42245cbda25cSStefano Zampini           } else {
4225a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4226a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
42275cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4228a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4229a3df083aSStefano Zampini             }
42305cbda25cSStefano Zampini           }
4231a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4232a3df083aSStefano Zampini         }
423306656605SStefano Zampini       } else {
4234c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
423506656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4236ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4237ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
423806656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
423906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
424006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
424106656605SStefano Zampini         }
4242c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
424306656605SStefano Zampini       }
424480677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4245c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4246ffd830a3SStefano Zampini       /* S_VV and S_CV */
424706656605SStefano Zampini       if (n_constraints) {
424806656605SStefano Zampini         Mat B;
424980677318SStefano Zampini 
4250ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
425180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4252ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4253ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
425480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
425580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
425680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
425780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
425880677318SStefano Zampini         }
4259ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
426080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
426180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4262ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
426380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
426406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4265ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4266ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
426706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
426806656605SStefano Zampini       }
4269ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4270ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4271ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4272ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4273ffd830a3SStefano Zampini       }
427406656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
427514393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
427614393ed6SStefano Zampini       if (need_benign_correction) {
4277df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
427814393ed6SStefano Zampini         PetscScalar      *marr,*sums;
427914393ed6SStefano Zampini 
428014393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4281f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4282df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
428314393ed6SStefano Zampini           const PetscScalar *vals;
428414393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
428514393ed6SStefano Zampini           PetscInt          n,j,nz;
428614393ed6SStefano Zampini 
4287df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4288df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
428914393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
429014393ed6SStefano Zampini             PetscInt k;
429114393ed6SStefano Zampini             sums[j] = 0.;
429214393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
429314393ed6SStefano Zampini           }
429414393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
429514393ed6SStefano Zampini           for (j=0;j<n;j++) {
429614393ed6SStefano Zampini             PetscScalar val = vals[j];
429714393ed6SStefano Zampini             PetscInt k;
429814393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
429914393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
430014393ed6SStefano Zampini             }
430114393ed6SStefano Zampini           }
430214393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4303df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
430414393ed6SStefano Zampini         }
430514393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4306f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
430714393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
430814393ed6SStefano Zampini       }
430980677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
431006656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
431106656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
431206656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
431306656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
431406656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
431506656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
431606656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4317d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4318019a44ceSStefano Zampini     } else {
4319d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4320d16cbb6bSStefano Zampini     }
432121eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4322d16cbb6bSStefano Zampini 
432306656605SStefano Zampini     /* coarse basis functions */
432406656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
432516f15bc4SStefano Zampini       PetscScalar *y;
432616f15bc4SStefano Zampini 
4327ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
432806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
432906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
433006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
433106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
433206656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
433306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
433406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
433506656605SStefano Zampini 
433606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
43374f1b2e48SStefano Zampini         PetscInt j;
43384f1b2e48SStefano Zampini 
433906656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
434006656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
434106656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
434206656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
434306656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
43444f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
434506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
434606656605SStefano Zampini       }
434706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
434806656605SStefano Zampini     }
434904708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
435004708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
435106656605SStefano Zampini   }
43525cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
435306656605SStefano Zampini 
435406656605SStefano Zampini   if (n_constraints) {
435506656605SStefano Zampini     Mat B;
435606656605SStefano Zampini 
4357ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
435806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
435980677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
436006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
436106656605SStefano Zampini     if (n_vertices) {
436203dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
436380677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
436480677318SStefano Zampini       } else {
436580677318SStefano Zampini         Mat S_VCt;
436680677318SStefano Zampini 
4367ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4368ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
436972b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4370ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4371ffd830a3SStefano Zampini         }
437280677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
437380677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
437480677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
437580677318SStefano Zampini       }
437606656605SStefano Zampini     }
437706656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
437806656605SStefano Zampini     /* coarse basis functions */
437906656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
438006656605SStefano Zampini       PetscScalar *y;
438106656605SStefano Zampini 
4382ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
438306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
438406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
438506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
438606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
438706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
438806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
438906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
43904f1b2e48SStefano Zampini         PetscInt j;
43914f1b2e48SStefano Zampini 
439206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
439306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
439406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
439506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
439606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
43974f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
439806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
439906656605SStefano Zampini       }
440006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
440106656605SStefano Zampini     }
440206656605SStefano Zampini   }
440380677318SStefano Zampini   if (n_constraints) {
440480677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
440580677318SStefano Zampini   }
44064f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
440772b8c272SStefano Zampini 
440872b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
440972b8c272SStefano Zampini   if (pcbddc->benign_n) {
441072b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
441172b8c272SStefano Zampini     IS          is_dummy;
441272b8c272SStefano Zampini     PetscScalar *data;
441372b8c272SStefano Zampini     PetscInt    j;
441472b8c272SStefano Zampini 
441572b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44167dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
441772b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
441872b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
441986c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
442072b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
442172b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
442272b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
442372b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
442472b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
442572b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
442672b8c272SStefano Zampini       }
442772b8c272SStefano Zampini     }
442872b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
442972b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
443072b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
443172b8c272SStefano Zampini   }
4432019a44ceSStefano Zampini 
443306656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
44343301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4435ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4436ffd830a3SStefano Zampini     PetscScalar *marray;
443706656605SStefano Zampini 
443806656605SStefano Zampini     if (n_constraints) {
4439ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
444006656605SStefano Zampini 
4441abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
444206656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4443ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
444416f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
444506656605SStefano Zampini       if (n_vertices) {
4446ffd830a3SStefano Zampini         Mat S_VCT;
444706656605SStefano Zampini 
444806656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4449ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
445016f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
445106656605SStefano Zampini       }
4452ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
44535b782168SStefano Zampini     } else {
44545b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
445506656605SStefano Zampini     }
445616f15bc4SStefano Zampini     if (n_vertices && n_R) {
4457ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4458ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4459ffd830a3SStefano Zampini       PetscInt       n;
4460ffd830a3SStefano Zampini       PetscBool      flg_row;
446106656605SStefano Zampini 
4462ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4463af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4464ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4465ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4466ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4467ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4468ffd830a3SStefano Zampini         PetscInt j;
4469ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4470ffd830a3SStefano Zampini       }
4471ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4472ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4473ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
447406656605SStefano Zampini     }
447506656605SStefano Zampini 
4476ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4477abc8f43dSstefano_zampini     if (n_vertices) {
4478ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4479ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4480ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4481ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
448206656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
448306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
448406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
448506656605SStefano Zampini       }
4486ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4487abc8f43dSstefano_zampini     }
44885b782168SStefano Zampini     if (B_C) {
4489ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4490ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4491ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4492ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4493ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4494ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4495ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
449606656605SStefano Zampini       }
4497ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
44985b782168SStefano Zampini     }
449906656605SStefano Zampini     /* coarse basis functions */
450006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
450106656605SStefano Zampini       PetscScalar *y;
450206656605SStefano Zampini 
4503ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
450406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
450506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
450606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450806656605SStefano Zampini       if (i<n_vertices) {
450906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
451006656605SStefano Zampini       }
451106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
451206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
451306656605SStefano Zampini 
451406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
451506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
451606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
451706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
451806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
451906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
452006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
452106656605SStefano Zampini       }
452206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
452306656605SStefano Zampini     }
4524ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4525ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
452606656605SStefano Zampini   }
4527a6e023c1Sstefano_zampini 
4528d62866d3SStefano Zampini   /* free memory */
452988ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
453006656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
453106656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
453206656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
453306656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4534d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4535d62866d3SStefano Zampini   if (n_vertices) {
4536d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4537d62866d3SStefano Zampini   }
4538d62866d3SStefano Zampini   if (n_constraints) {
4539d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4540d62866d3SStefano Zampini   }
454188ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
454288ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
454388ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4544d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
454588ebb749SStefano Zampini     Mat         coarse_sub_mat;
454625084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
454788ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
454888ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
454988ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
45508bec7fa6SStefano Zampini     Mat         C_B,CPHI;
45518bec7fa6SStefano Zampini     IS          is_dummy;
45528bec7fa6SStefano Zampini     Vec         mones;
455388ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
455488ebb749SStefano Zampini     PetscReal   real_value;
455588ebb749SStefano Zampini 
4556a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4557a3df083aSStefano Zampini       Mat A;
4558a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
45597dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
45607dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
45617dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
45627dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4563a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4564a3df083aSStefano Zampini     } else {
456588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
456688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
456788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
456888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4569a3df083aSStefano Zampini     }
457088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
457188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4572ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
457388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
457488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
457588ebb749SStefano Zampini     }
457688ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
457788ebb749SStefano Zampini 
457825084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
45793301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
458025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4581ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
458288ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
458388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
458488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
458588ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
458688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
458788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
458888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
458988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
459088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
459188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
459288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
459388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
459488ebb749SStefano Zampini     } else {
459588ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
459688ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
459788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
459888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
459988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
460088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
460188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
460288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
460388ebb749SStefano Zampini     }
460488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
460588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
460688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4607511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
46084f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4609fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4610d12edf2fSStefano Zampini       PetscScalar *data,*data2;
46114f1b2e48SStefano Zampini       PetscInt    j;
4612d12edf2fSStefano Zampini 
46134f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
46147dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4615d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
461686c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4617d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4618d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
46194f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
46204f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4621d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
46224f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
46234f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
46244f1b2e48SStefano Zampini         }
4625d12edf2fSStefano Zampini       }
4626d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4627d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4628d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4629d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4630d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4631d12edf2fSStefano Zampini     }
4632d12edf2fSStefano Zampini #if 0
4633d12edf2fSStefano Zampini   {
4634d12edf2fSStefano Zampini     PetscViewer viewer;
4635d12edf2fSStefano Zampini     char filename[256];
4636ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4637d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4638a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4639ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4640ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4641ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4642d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4643a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4644ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4645ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
464672b8c272SStefano Zampini     }
4647ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4648ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4649ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4650ffd830a3SStefano Zampini     }
4651ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4652ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4653ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4654ffd830a3SStefano Zampini     }
465572b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4656ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4657ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4658ffd830a3SStefano Zampini     }
4659fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4660fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4661fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4662fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4663fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4664fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4665fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4666fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4667fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4668fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4669d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4670d12edf2fSStefano Zampini   }
4671d12edf2fSStefano Zampini #endif
467281d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
46738bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
46741575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
467506656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
46768bec7fa6SStefano Zampini 
46778bec7fa6SStefano Zampini     /* check constraints */
4678a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
46797dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
46804f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
46818bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4682a00504b5SStefano Zampini     } else {
4683a00504b5SStefano Zampini       PetscScalar *data;
4684a00504b5SStefano Zampini       Mat         tmat;
4685a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4686a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4687a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4688a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4689a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4690a00504b5SStefano Zampini     }
46918bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
46928bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
46938bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
46948bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4695bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4696ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4697bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4698bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4699bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4700bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4701bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
470288ebb749SStefano Zampini     }
47038bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
47048bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
47058bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
47068bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
470725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
470888ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
470988ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
471088ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
471188ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
471288ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
471388ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
471488ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
471588ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
471688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
471788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4718ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
471988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
472088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
472188ebb749SStefano Zampini     }
472288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
472388ebb749SStefano Zampini   }
47248629588bSStefano Zampini   /* get back data */
47258629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
472688ebb749SStefano Zampini   PetscFunctionReturn(0);
472788ebb749SStefano Zampini }
472888ebb749SStefano Zampini 
47297dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4730aa0d41d4SStefano Zampini {
4731d65f70fdSStefano Zampini   Mat            *work_mat;
4732d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4733d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4734c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4735aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4736aa0d41d4SStefano Zampini 
4737aa0d41d4SStefano Zampini   PetscFunctionBegin;
4738d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4739d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4740d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4741d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4742aa0d41d4SStefano Zampini 
4743d65f70fdSStefano Zampini   if (!rsorted) {
4744906d46d4SStefano Zampini     const PetscInt *idxs;
4745906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4746aa0d41d4SStefano Zampini 
4747d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4748d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4749d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4750d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4751aa0d41d4SStefano Zampini     }
4752d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4753d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4754d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4755d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4756aa0d41d4SStefano Zampini     }
4757d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4758d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4759d65f70fdSStefano Zampini   } else {
4760d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4761d65f70fdSStefano Zampini     isrow_s = isrow;
4762aa0d41d4SStefano Zampini   }
4763906d46d4SStefano Zampini 
4764d65f70fdSStefano Zampini   if (!csorted) {
4765d65f70fdSStefano Zampini     if (isrow == iscol) {
4766d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4767d65f70fdSStefano Zampini       iscol_s = isrow_s;
4768d65f70fdSStefano Zampini     } else {
4769d65f70fdSStefano Zampini       const PetscInt *idxs;
4770d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4771906d46d4SStefano Zampini 
4772d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4773d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4774d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4775d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4776d65f70fdSStefano Zampini       }
4777d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4778d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4779d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4780d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4781d65f70fdSStefano Zampini       }
4782d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4783d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4784d65f70fdSStefano Zampini     }
4785d65f70fdSStefano Zampini   } else {
4786d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4787d65f70fdSStefano Zampini     iscol_s = iscol;
4788d65f70fdSStefano Zampini   }
4789d65f70fdSStefano Zampini 
47907dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4791d65f70fdSStefano Zampini 
4792d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4793906d46d4SStefano Zampini     Mat      new_mat;
4794d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4795906d46d4SStefano Zampini 
4796d65f70fdSStefano Zampini     if (!rsorted) {
4797d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4798d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4799d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4800d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4801906d46d4SStefano Zampini       }
4802d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4803d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4804d65f70fdSStefano Zampini     } else {
4805d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4806906d46d4SStefano Zampini     }
4807d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4808d65f70fdSStefano Zampini 
4809d65f70fdSStefano Zampini     if (!csorted) {
4810d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4811d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4812d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4813d65f70fdSStefano Zampini       } else {
4814d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4815f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4816d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4817d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4818d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4819d65f70fdSStefano Zampini         }
4820d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4821d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4822d65f70fdSStefano Zampini       }
4823d65f70fdSStefano Zampini     } else {
4824d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4825d65f70fdSStefano Zampini     }
4826d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4827d65f70fdSStefano Zampini 
4828d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4829d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4830d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4831d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4832d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4833d65f70fdSStefano Zampini   }
4834d65f70fdSStefano Zampini 
4835d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4836d65f70fdSStefano Zampini   *B = work_mat[0];
4837d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4838d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4839d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4840d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4841d65f70fdSStefano Zampini }
4842d65f70fdSStefano Zampini 
48435e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4844aa0d41d4SStefano Zampini {
4845aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
48465e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4847022d8d2bSstefano_zampini   Mat            new_mat,lA;
48485e8657edSStefano Zampini   IS             is_local,is_global;
4849d65f70fdSStefano Zampini   PetscInt       local_size;
4850d65f70fdSStefano Zampini   PetscBool      isseqaij;
4851aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4852aa0d41d4SStefano Zampini 
4853aa0d41d4SStefano Zampini   PetscFunctionBegin;
4854aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
48555e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
48565e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4857b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4858aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
48597dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4860aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4861906d46d4SStefano Zampini 
4862906d46d4SStefano Zampini   /* check */
4863906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4864906d46d4SStefano Zampini     Vec       x,x_change;
4865906d46d4SStefano Zampini     PetscReal error;
4866906d46d4SStefano Zampini 
48675e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4868906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
48695e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4870e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4871e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4872d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
487388428137SStefano Zampini     if (!pcbddc->change_interior) {
487488428137SStefano Zampini       const PetscScalar *x,*y,*v;
487588428137SStefano Zampini       PetscReal         lerror = 0.;
487688428137SStefano Zampini       PetscInt          i;
487788428137SStefano Zampini 
487888428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
487988428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
488088428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
488188428137SStefano Zampini       for (i=0;i<local_size;i++)
488288428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
488388428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
488488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
488588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
488688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
488788428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4888637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4889637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4890637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4891637e8532SStefano Zampini         } else {
4892637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4893637e8532SStefano Zampini         }
4894637e8532SStefano Zampini       }
489588428137SStefano Zampini     }
4896e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4897e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4898906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4899906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4900637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4901637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4902637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4903637e8532SStefano Zampini       } else {
4904637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4905637e8532SStefano Zampini       }
4906637e8532SStefano Zampini     }
4907906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4908906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4909906d46d4SStefano Zampini   }
4910906d46d4SStefano Zampini 
4911022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4912022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4913022d8d2bSstefano_zampini 
491422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
49159b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
491622d5777bSStefano Zampini   if (isseqaij) {
4917a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4918a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4919022d8d2bSstefano_zampini     if (lA) {
4920022d8d2bSstefano_zampini       Mat work;
4921022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4922022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4923022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4924022d8d2bSstefano_zampini     }
4925aa0d41d4SStefano Zampini   } else {
4926a00504b5SStefano Zampini     Mat work_mat;
49271cf9b237SStefano Zampini 
4928a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4929aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4930a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
49311d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4932022d8d2bSstefano_zampini     if (lA) {
4933022d8d2bSstefano_zampini       Mat work;
4934022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4935022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4936022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4937022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4938022d8d2bSstefano_zampini     }
4939aa0d41d4SStefano Zampini   }
49403301b35fSStefano Zampini   if (matis->A->symmetric_set) {
49413301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4942e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
49433301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4944e496cd5dSStefano Zampini #endif
49453301b35fSStefano Zampini   }
4946d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4947aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4948aa0d41d4SStefano Zampini }
4949aa0d41d4SStefano Zampini 
49508ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4951a64d13efSStefano Zampini {
4952a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4953a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4954d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
495553892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
49563a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
49573a50541eSStefano Zampini   PetscInt        vbs,bs;
49586816873aSStefano Zampini   PetscBT         bitmask=NULL;
4959a64d13efSStefano Zampini   PetscErrorCode  ierr;
4960a64d13efSStefano Zampini 
4961a64d13efSStefano Zampini   PetscFunctionBegin;
4962b23d619eSStefano Zampini   /*
4963b23d619eSStefano Zampini     No need to setup local scatters if
4964b23d619eSStefano Zampini       - primal space is unchanged
4965b23d619eSStefano Zampini         AND
4966b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4967b23d619eSStefano Zampini         AND
4968b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4969b23d619eSStefano Zampini   */
4970b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4971f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4972f4ddd8eeSStefano Zampini   }
4973f4ddd8eeSStefano Zampini   /* destroy old objects */
4974f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4975f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4976f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4977a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4978b371cd4fSStefano Zampini   n_B = pcis->n_B;
4979b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4980b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
49813a50541eSStefano Zampini 
4982a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
49836816873aSStefano Zampini 
498453892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4985b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4986854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4987a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4988a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
49890e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4990a64d13efSStefano Zampini     }
4991a64d13efSStefano Zampini 
4992a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
49934641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
49946816873aSStefano Zampini         idx_R_local[n_R++] = i;
4995a64d13efSStefano Zampini       }
4996a64d13efSStefano Zampini     }
4997df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4998df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
49996816873aSStefano Zampini 
5000df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5001df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
50026816873aSStefano Zampini   }
50033a50541eSStefano Zampini 
50043a50541eSStefano Zampini   /* Block code */
50053a50541eSStefano Zampini   vbs = 1;
50063a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
50073a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
50083a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
50093a50541eSStefano Zampini     PetscInt  *vary;
5010b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5011785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
50123a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
5013d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5014d3df7717SStefano 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 */
50150e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5016d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
50173a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
50183a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
50193a50541eSStefano Zampini           break;
50203a50541eSStefano Zampini         }
50213a50541eSStefano Zampini       }
5022d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5023d3df7717SStefano Zampini     } else {
5024d3df7717SStefano Zampini       /* Verify directly the R set */
5025d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5026d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5027d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5028d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5029d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5030d3df7717SStefano Zampini             break;
5031d3df7717SStefano Zampini           }
5032d3df7717SStefano Zampini         }
5033d3df7717SStefano Zampini       }
5034d3df7717SStefano Zampini     }
50353a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
50363a50541eSStefano Zampini       vbs = bs;
50373a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
50383a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
50393a50541eSStefano Zampini       }
50403a50541eSStefano Zampini     }
50413a50541eSStefano Zampini   }
50423a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5043b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5044df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
504553892102SStefano Zampini 
5046df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5047df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
504853892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5049df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
505053892102SStefano Zampini   } else {
50513a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
505253892102SStefano Zampini   }
5053a64d13efSStefano Zampini 
5054a64d13efSStefano Zampini   /* print some info if requested */
5055a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5056a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5057a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50581575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5059a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
5060a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
50614f1b2e48SStefano 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);
5062a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5063a64d13efSStefano Zampini   }
5064a64d13efSStefano Zampini 
5065a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5066b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
50676816873aSStefano Zampini     IS       is_aux1,is_aux2;
50686816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
50696816873aSStefano Zampini 
50703a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5071854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5072854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5073a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
50744641a718SStefano Zampini     for (i=0; i<n_D; i++) {
50754641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
50764641a718SStefano Zampini     }
5077a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5078a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
50794641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
50804641a718SStefano Zampini         aux_array1[j++] = i;
5081a64d13efSStefano Zampini       }
5082a64d13efSStefano Zampini     }
5083a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5084a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5085a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
50864641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
50874641a718SStefano Zampini         aux_array2[j++] = i;
5088a64d13efSStefano Zampini       }
5089a64d13efSStefano Zampini     }
5090a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5091a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
5092a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5093a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5094a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5095a64d13efSStefano Zampini 
50968eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5097785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5098a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
50994641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
51004641a718SStefano Zampini           aux_array1[j++] = i;
5101a64d13efSStefano Zampini         }
5102a64d13efSStefano Zampini       }
5103a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5104a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5105a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5106a64d13efSStefano Zampini     }
51074641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
51083a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5109d62866d3SStefano Zampini   } else {
5110df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
51116816873aSStefano Zampini     IS                 tis;
51126816873aSStefano Zampini     PetscInt           schur_size;
51136816873aSStefano Zampini 
5114df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
51156816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
5116df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
51176816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
51186816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
51196816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
51206816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
51216816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5122d62866d3SStefano Zampini     }
5123d62866d3SStefano Zampini   }
5124a64d13efSStefano Zampini   PetscFunctionReturn(0);
5125a64d13efSStefano Zampini }
5126a64d13efSStefano Zampini 
5127304d26faSStefano Zampini 
5128684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5129304d26faSStefano Zampini {
5130304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5131304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5132304d26faSStefano Zampini   PC             pc_temp;
5133304d26faSStefano Zampini   Mat            A_RR;
5134f4ddd8eeSStefano Zampini   MatReuse       reuse;
5135304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5136304d26faSStefano Zampini   PetscReal      value;
513704708bb6SStefano Zampini   PetscInt       n_D,n_R;
513835529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
5139304d26faSStefano Zampini   PetscErrorCode ierr;
5140e604994aSStefano Zampini   /* prefixes stuff */
5141312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5142e604994aSStefano Zampini   size_t         len;
5143304d26faSStefano Zampini 
5144304d26faSStefano Zampini   PetscFunctionBegin;
5145304d26faSStefano Zampini 
5146e604994aSStefano Zampini   /* compute prefixes */
5147e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5148e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5149e604994aSStefano Zampini   if (!pcbddc->current_level) {
5150a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5151a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5152a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5153a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5154e604994aSStefano Zampini   } else {
515535529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5156e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5157e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5158312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5159312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5160a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
516134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
516234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5163a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5164a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5165a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5166a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5167e604994aSStefano Zampini   }
5168e604994aSStefano Zampini 
5169304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5170684f6988SStefano Zampini   if (dirichlet) {
5171d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5172450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
51739a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
5174450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5175a3df083aSStefano Zampini         Mat    A_IIn;
5176a3df083aSStefano Zampini 
5177a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5178a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5179a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5180a3df083aSStefano Zampini       }
5181450f8f5eSStefano Zampini     }
51823301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
51833301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
5184964fefecSStefano Zampini     }
5185ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5186964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
5187304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
5188cd18cfedSStefano Zampini       void (*f)(void) = 0;
5189cd18cfedSStefano Zampini 
5190304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5191304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5192304d26faSStefano Zampini       /* default */
5193304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5194e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
51959577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5196304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
51979577ea80SStefano Zampini       if (issbaij) {
51989577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
51999577ea80SStefano Zampini       } else {
5200304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
52019577ea80SStefano Zampini       }
5202304d26faSStefano Zampini       /* Allow user's customization */
5203304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5204cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5205cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5206cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5207cd18cfedSStefano Zampini         const PetscInt *idxs;
5208cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5209cd18cfedSStefano Zampini 
5210cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5211cd18cfedSStefano Zampini         ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5212cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5213cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5214cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5215cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5216cd18cfedSStefano Zampini           }
5217cd18cfedSStefano Zampini         }
5218cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5219cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5220cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5221cd18cfedSStefano Zampini       }
5222304d26faSStefano Zampini     }
5223d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5224b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5225df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5226d62866d3SStefano Zampini 
5227df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5228d5574798SStefano Zampini     }
5229304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5230304d26faSStefano Zampini     if (!n_D) {
5231304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5232304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5233304d26faSStefano Zampini     }
5234304d26faSStefano Zampini     /* set ksp_D into pcis data */
5235304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5236304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5237304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5238684f6988SStefano Zampini   }
5239304d26faSStefano Zampini 
5240304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5241684f6988SStefano Zampini   A_RR = 0;
5242684f6988SStefano Zampini   if (neumann) {
5243d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
524404708bb6SStefano Zampini     PetscInt        ibs,mbs;
52450aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
524604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
52470aa714b2SStefano Zampini 
52480aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
52490aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
52500aa714b2SStefano Zampini       IS iP;
52510aa714b2SStefano Zampini 
52520aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
52530aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
52540aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
52550aa714b2SStefano Zampini     }
5256f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
52578ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5258f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5259f4ddd8eeSStefano Zampini       PetscInt nn_R;
526081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5261f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5262f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5263f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5264f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5265f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5266f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5267f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5268727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5269f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5270f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5271f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5272f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5273f4ddd8eeSStefano Zampini         }
5274f4ddd8eeSStefano Zampini       }
5275f4ddd8eeSStefano Zampini       /* last check */
5276d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5277f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5278f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5279f4ddd8eeSStefano Zampini       }
5280f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5281f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5282f4ddd8eeSStefano Zampini     }
5283a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5284af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5285af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
528604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
528704708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
528804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
528904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
529004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5291af732b37SStefano Zampini       } else {
5292511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
52936816873aSStefano Zampini       }
529404708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
529504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
529604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
529704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
529804708bb6SStefano Zampini       } else {
5299511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
530004708bb6SStefano Zampini       }
530104708bb6SStefano Zampini     }
5302a00504b5SStefano Zampini     /* extract A_RR */
53030aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5304a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5305a00504b5SStefano Zampini 
5306a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
530716e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5308a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
530916e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
531016e386b8SStefano Zampini         } else {
53117dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5312a00504b5SStefano Zampini         }
5313a00504b5SStefano Zampini       } else {
5314a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5315a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5316a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5317a00504b5SStefano Zampini       }
5318a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
53197dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
532016e386b8SStefano Zampini     }
53213301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
53223301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
53236816873aSStefano Zampini     }
5324f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5325cd18cfedSStefano Zampini       void (*f)(void) = 0;
5326cd18cfedSStefano Zampini 
5327304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5328304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5329304d26faSStefano Zampini       /* default */
5330304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5331e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5332304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
53339577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
53349577ea80SStefano Zampini       if (issbaij) {
53359577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
53369577ea80SStefano Zampini       } else {
5337304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
53389577ea80SStefano Zampini       }
5339304d26faSStefano Zampini       /* Allow user's customization */
5340304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5341cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5342cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5343cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5344cd18cfedSStefano Zampini         const PetscInt *idxs;
5345cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5346cd18cfedSStefano Zampini 
5347cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5348cd18cfedSStefano Zampini         ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5349cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5350cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5351cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5352cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5353cd18cfedSStefano Zampini           }
5354cd18cfedSStefano Zampini         }
5355cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5356cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5357cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5358cd18cfedSStefano Zampini       }
5359304d26faSStefano Zampini     }
5360304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5361304d26faSStefano Zampini     if (!n_R) {
5362304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5363304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5364304d26faSStefano Zampini     }
53655cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5366df4d28bfSStefano Zampini     /* Reuse solver if it is present */
53670aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5368df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5369d62866d3SStefano Zampini 
5370df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5371d62866d3SStefano Zampini     }
5372684f6988SStefano Zampini   }
5373304d26faSStefano Zampini 
5374684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5375684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
53761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5377684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5378684f6988SStefano Zampini   }
5379c7017625SStefano Zampini 
5380c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
538135529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5382c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5383c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5384c7017625SStefano Zampini   }
5385c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
538635529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5387c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5388c7017625SStefano Zampini   }
5389c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
539035529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5391c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5392c7017625SStefano Zampini   }
5393c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5394c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5395684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
53960fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
53970fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
53980fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
53990fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
54000fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5401e604994aSStefano 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);
540235529e7bSStefano Zampini       if (check_corr) {
5403c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5404c7017625SStefano Zampini       }
5405304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5406304d26faSStefano Zampini     }
5407684f6988SStefano Zampini     if (neumann) { /* Neumann */
54080fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
54090fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
54100fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
54110fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
54120fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5413e604994aSStefano 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);
541435529e7bSStefano Zampini       if (check_corr) {
5415c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5416c7017625SStefano Zampini       }
5417304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5418304d26faSStefano Zampini     }
5419684f6988SStefano Zampini   }
54205cbda25cSStefano Zampini   /* free Neumann problem's matrix */
54215cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5422304d26faSStefano Zampini   PetscFunctionReturn(0);
5423304d26faSStefano Zampini }
5424304d26faSStefano Zampini 
542580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5426674ae819SStefano Zampini {
5427674ae819SStefano Zampini   PetscErrorCode  ierr;
5428674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5429be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5430b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5431674ae819SStefano Zampini 
5432674ae819SStefano Zampini   PetscFunctionBegin;
5433b334f244SStefano Zampini   if (!reuse_solver) {
543480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
543520c7b377SStefano Zampini   }
543680677318SStefano Zampini   if (!pcbddc->switch_static) {
543780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
543880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
543980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
544020c7b377SStefano Zampini     }
5441b334f244SStefano Zampini     if (!reuse_solver) {
544280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
544380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
544420c7b377SStefano Zampini     } else {
5445df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5446be83ff47SStefano Zampini 
5447df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5448df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
544920c7b377SStefano Zampini     }
5450be83ff47SStefano Zampini   } else {
545180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
545680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
545780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
545880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5460674ae819SStefano Zampini     }
5461674ae819SStefano Zampini   }
5462b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
546380677318SStefano Zampini     if (applytranspose) {
546480677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
546580677318SStefano Zampini     } else {
546680677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
546780677318SStefano Zampini     }
5468be83ff47SStefano Zampini   } else {
5469df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5470be83ff47SStefano Zampini 
5471be83ff47SStefano Zampini     if (applytranspose) {
5472df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5473be83ff47SStefano Zampini     } else {
5474df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5475be83ff47SStefano Zampini     }
5476be83ff47SStefano Zampini   }
547780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
547880677318SStefano Zampini   if (!pcbddc->switch_static) {
5479b334f244SStefano Zampini     if (!reuse_solver) {
548080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
548180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5482be83ff47SStefano Zampini     } else {
5483df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5484be83ff47SStefano Zampini 
5485df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5486df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5487be83ff47SStefano Zampini     }
548880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
548980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
549080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
549180677318SStefano Zampini     }
549280677318SStefano Zampini   } else {
549380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
549480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
549580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
549680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
549780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
549880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
549980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
550080677318SStefano Zampini     }
550180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
550280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
550380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
550480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5505674ae819SStefano Zampini   }
5506674ae819SStefano Zampini   PetscFunctionReturn(0);
5507674ae819SStefano Zampini }
5508674ae819SStefano Zampini 
5509dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5510dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5511674ae819SStefano Zampini {
5512674ae819SStefano Zampini   PetscErrorCode ierr;
5513674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5514674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5515674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5516674ae819SStefano Zampini 
5517674ae819SStefano Zampini   PetscFunctionBegin;
5518dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
55194fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5520dc359a40SStefano Zampini     if (applytranspose) {
5521674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
55228eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5523dc359a40SStefano Zampini     } else {
5524674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5525674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
552615aaf578SStefano Zampini     }
55274fee134fSStefano Zampini   } else {
55284fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
55294fee134fSStefano Zampini   }
5530efc2fbd9SStefano Zampini 
5531efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
55324f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5533efc2fbd9SStefano Zampini     PetscScalar *array;
55344f1b2e48SStefano Zampini     PetscInt    j;
5535efc2fbd9SStefano Zampini 
5536efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
55374f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5538efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5539efc2fbd9SStefano Zampini   }
5540efc2fbd9SStefano Zampini 
554112edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
554212edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
554312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
554412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
554512edc857SStefano Zampini 
55469f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
554712edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
554851694757SStefano Zampini     Mat          coarse_mat;
5549964fefecSStefano Zampini     Vec          rhs,sol;
555051694757SStefano Zampini     MatNullSpace nullsp;
555127b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5552964fefecSStefano Zampini 
555327b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
555427b6a85dSStefano Zampini       PC        coarse_pc;
555527b6a85dSStefano Zampini 
555627b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
555727b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
555827b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
555927b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
556027b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
556127b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
55623bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
556327b6a85dSStefano Zampini       }
556427b6a85dSStefano Zampini     }
5565964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5566964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
556751694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
556851694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
556951694757SStefano Zampini     if (nullsp) {
557051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
557151694757SStefano Zampini     }
557212edc857SStefano Zampini     if (applytranspose) {
55739a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5574964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
55752701bc32SStefano Zampini     } else {
55761f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
55772701bc32SStefano Zampini         PC        coarse_pc;
55782701bc32SStefano Zampini 
55792701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
55802701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
55813e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
55822701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
558312edc857SStefano Zampini       } else {
5584964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
558512edc857SStefano Zampini       }
55862701bc32SStefano Zampini     }
55871d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
558827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
558927b6a85dSStefano Zampini       PC        coarse_pc;
559027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
559127b6a85dSStefano Zampini 
559227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
559327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
559427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
55953bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
559627b6a85dSStefano Zampini     }
559751694757SStefano Zampini     if (nullsp) {
559851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
559951694757SStefano Zampini     }
560012edc857SStefano Zampini   }
5601674ae819SStefano Zampini 
5602674ae819SStefano Zampini   /* Local solution on R nodes */
56034fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
560480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
56059f00e9b4SStefano Zampini   }
56069f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
56079f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
560812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5609674ae819SStefano Zampini 
56104fee134fSStefano Zampini   /* Sum contributions from the two levels */
56114fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5612dc359a40SStefano Zampini     if (applytranspose) {
5613dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5614dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5615dc359a40SStefano Zampini     } else {
5616674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
56178eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5618dc359a40SStefano Zampini     }
5619efc2fbd9SStefano Zampini     /* store p0 */
56204f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5621efc2fbd9SStefano Zampini       PetscScalar *array;
56224f1b2e48SStefano Zampini       PetscInt    j;
5623efc2fbd9SStefano Zampini 
5624efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
56254f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5626efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5627efc2fbd9SStefano Zampini     }
56284fee134fSStefano Zampini   } else { /* expand the coarse solution */
56294fee134fSStefano Zampini     if (applytranspose) {
56304fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
56314fee134fSStefano Zampini     } else {
56324fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
56334fee134fSStefano Zampini     }
56344fee134fSStefano Zampini   }
5635674ae819SStefano Zampini   PetscFunctionReturn(0);
5636674ae819SStefano Zampini }
5637674ae819SStefano Zampini 
563812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5639674ae819SStefano Zampini {
5640674ae819SStefano Zampini   PetscErrorCode ierr;
5641674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
564258da7f69SStefano Zampini   PetscScalar    *array;
564312edc857SStefano Zampini   Vec            from,to;
5644674ae819SStefano Zampini 
5645674ae819SStefano Zampini   PetscFunctionBegin;
564612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
564712edc857SStefano Zampini     from = pcbddc->coarse_vec;
564812edc857SStefano Zampini     to = pcbddc->vec1_P;
564912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
565012edc857SStefano Zampini       Vec tvec;
565158da7f69SStefano Zampini 
565258da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
565358da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
565412edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
565558da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
565658da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
565758da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
565812edc857SStefano Zampini     }
565912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
566012edc857SStefano Zampini     from = pcbddc->vec1_P;
566112edc857SStefano Zampini     to = pcbddc->coarse_vec;
566212edc857SStefano Zampini   }
566312edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5664674ae819SStefano Zampini   PetscFunctionReturn(0);
5665674ae819SStefano Zampini }
5666674ae819SStefano Zampini 
566712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5668674ae819SStefano Zampini {
5669674ae819SStefano Zampini   PetscErrorCode ierr;
5670674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
567158da7f69SStefano Zampini   PetscScalar    *array;
567212edc857SStefano Zampini   Vec            from,to;
5673674ae819SStefano Zampini 
5674674ae819SStefano Zampini   PetscFunctionBegin;
567512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
567612edc857SStefano Zampini     from = pcbddc->coarse_vec;
567712edc857SStefano Zampini     to = pcbddc->vec1_P;
567812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
567912edc857SStefano Zampini     from = pcbddc->vec1_P;
568012edc857SStefano Zampini     to = pcbddc->coarse_vec;
568112edc857SStefano Zampini   }
568212edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
568312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
568412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
568512edc857SStefano Zampini       Vec tvec;
568658da7f69SStefano Zampini 
568712edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
568858da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
568958da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
569058da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
569158da7f69SStefano Zampini     }
569258da7f69SStefano Zampini   } else {
569358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
569458da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
569512edc857SStefano Zampini     }
569612edc857SStefano Zampini   }
5697674ae819SStefano Zampini   PetscFunctionReturn(0);
5698674ae819SStefano Zampini }
5699674ae819SStefano Zampini 
5700984c4197SStefano Zampini /* uncomment for testing purposes */
5701984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5702674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5703674ae819SStefano Zampini {
5704674ae819SStefano Zampini   PetscErrorCode    ierr;
5705674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5706674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5707674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5708984c4197SStefano Zampini   /* one and zero */
5709984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5710984c4197SStefano Zampini   /* space to store constraints and their local indices */
57119162d606SStefano Zampini   PetscScalar       *constraints_data;
57129162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
57139162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
57149162d606SStefano Zampini   PetscInt          *constraints_n;
5715984c4197SStefano Zampini   /* iterators */
5716b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5717984c4197SStefano Zampini   /* BLAS integers */
5718e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5719e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5720c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5721727cdba6SStefano Zampini   /* reuse */
57220e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
57230e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5724984c4197SStefano Zampini   /* change of basis */
5725b3d85658SStefano Zampini   PetscBool         qr_needed;
57269162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5727984c4197SStefano Zampini   /* auxiliary stuff */
572864efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
57298a0068c3SStefano Zampini   PetscInt          ncc;
5730984c4197SStefano Zampini   /* some quantities */
573145a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5732a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
573357715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
5734984c4197SStefano Zampini 
5735674ae819SStefano Zampini   PetscFunctionBegin;
573657715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
57378e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
57388e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57398e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
574016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5741088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5742088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
57430e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
57440e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
57450e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
57460e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
57470e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5748088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5749cf5a6209SStefano Zampini 
5750cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
57519162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5752cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5753cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5754cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5755cf5a6209SStefano Zampini     PetscScalar  *array;
5756cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5757cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5758674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5759b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5760674ae819SStefano Zampini     PetscScalar  *work;
5761674ae819SStefano Zampini     PetscReal    *singular_vals;
5762674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5763674ae819SStefano Zampini     PetscReal    *rwork;
5764674ae819SStefano Zampini #endif
5765674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5766674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5767674ae819SStefano Zampini #else
5768964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5769964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5770674ae819SStefano Zampini #endif
5771674ae819SStefano Zampini 
5772674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5773d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5774e4d548c7SStefano Zampini     /* print some info */
57755c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5776e4d548c7SStefano Zampini       PetscInt nv;
5777e4d548c7SStefano Zampini 
5778c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5779e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5780e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5781e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5782e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5783e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5784e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5785e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5786e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5787e4d548c7SStefano Zampini     }
5788e4d548c7SStefano Zampini 
5789d06fc5fdSStefano Zampini     /* free unneeded index sets */
5790d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5791d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5792674ae819SStefano Zampini     }
5793d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5794d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5795d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5796d06fc5fdSStefano Zampini       }
5797d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5798d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5799d06fc5fdSStefano Zampini     }
5800d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5801d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5802d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5803d06fc5fdSStefano Zampini       }
5804d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5805d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5806d06fc5fdSStefano Zampini     }
580770022509SStefano Zampini 
5808674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5809674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5810674ae819SStefano Zampini     if (nearnullsp) {
5811674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5812f4ddd8eeSStefano Zampini       /* remove any stored info */
5813f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5814f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5815f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5816f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5817f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5818473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5819f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5820f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5821f4ddd8eeSStefano Zampini       }
5822984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5823984c4197SStefano Zampini       nnsp_size = 0;
5824674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5825674ae819SStefano Zampini     }
5826984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5827984c4197SStefano Zampini     max_constraints = nnsp_size;
5828984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5829984c4197SStefano Zampini 
5830674ae819SStefano Zampini     /*
5831674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
58329162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
58339162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
58349162d606SStefano Zampini          There can be multiple constraints per connected component
5835674ae819SStefano Zampini                                                                                                                                                            */
5836674ae819SStefano Zampini     n_vertices = 0;
5837674ae819SStefano Zampini     if (ISForVertices) {
5838674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5839674ae819SStefano Zampini     }
58409162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
58419162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
58429162d606SStefano Zampini 
58439162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
58449162d606SStefano Zampini     total_counts *= max_constraints;
5845674ae819SStefano Zampini     total_counts += n_vertices;
58464641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
58479162d606SStefano Zampini 
5848674ae819SStefano Zampini     total_counts = 0;
5849674ae819SStefano Zampini     max_size_of_constraint = 0;
5850674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
58519162d606SStefano Zampini       IS used_is;
5852674ae819SStefano Zampini       if (i<n_ISForEdges) {
58539162d606SStefano Zampini         used_is = ISForEdges[i];
5854674ae819SStefano Zampini       } else {
58559162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5856674ae819SStefano Zampini       }
58579162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5858674ae819SStefano Zampini       total_counts += j;
5859674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5860674ae819SStefano Zampini     }
58619162d606SStefano 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);
58629162d606SStefano Zampini 
5863984c4197SStefano Zampini     /* get local part of global near null space vectors */
5864785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5865984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5866984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5867e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5868e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5869984c4197SStefano Zampini     }
5870674ae819SStefano Zampini 
5871242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5872242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5873a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5874242a89d7SStefano Zampini 
5875984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5876a773dcb8SStefano Zampini     if (!skip_lapack) {
5877674ae819SStefano Zampini       PetscScalar temp_work;
5878911cabfeSStefano Zampini 
5879674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5880984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5881785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5882785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5883785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5884674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5885785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5886674ae819SStefano Zampini #endif
5887674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5888c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5889c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5890674ae819SStefano Zampini       lwork = -1;
5891674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5892674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5893c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5894674ae819SStefano Zampini #else
5895c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5896674ae819SStefano Zampini #endif
5897674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5898984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5899674ae819SStefano Zampini #else /* on missing GESVD */
5900674ae819SStefano Zampini       /* SVD */
5901674ae819SStefano Zampini       PetscInt max_n,min_n;
5902674ae819SStefano Zampini       max_n = max_size_of_constraint;
5903984c4197SStefano Zampini       min_n = max_constraints;
5904984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5905674ae819SStefano Zampini         min_n = max_size_of_constraint;
5906984c4197SStefano Zampini         max_n = max_constraints;
5907674ae819SStefano Zampini       }
5908785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5909674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5910785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5911674ae819SStefano Zampini #endif
5912674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5913674ae819SStefano Zampini       lwork = -1;
5914e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5915e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5916b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5917674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5918674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
59199162d606SStefano 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));
5920674ae819SStefano Zampini #else
59219162d606SStefano 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));
5922674ae819SStefano Zampini #endif
5923674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5924984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5925984c4197SStefano Zampini #endif /* on missing GESVD */
5926674ae819SStefano Zampini       /* Allocate optimal workspace */
5927674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5928854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5929674ae819SStefano Zampini     }
5930674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5931674ae819SStefano Zampini     total_counts = 0;
59329162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
59339162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5934674ae819SStefano Zampini     /* vertices */
59359162d606SStefano Zampini     if (n_vertices) {
5936674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
59379162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5938674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
59399162d606SStefano Zampini         constraints_n[total_counts] = 1;
59409162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
59419162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
59429162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5943674ae819SStefano Zampini         total_counts++;
5944674ae819SStefano Zampini       }
5945674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5946674ae819SStefano Zampini       n_vertices = total_counts;
5947674ae819SStefano Zampini     }
5948984c4197SStefano Zampini 
5949674ae819SStefano Zampini     /* edges and faces */
59509162d606SStefano Zampini     total_counts_cc = total_counts;
5951911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
59529162d606SStefano Zampini       IS        used_is;
59539162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
59549162d606SStefano Zampini 
5955911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
59569162d606SStefano Zampini         used_is = ISForEdges[ncc];
5957984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5958674ae819SStefano Zampini       } else {
59599162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5960984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5961674ae819SStefano Zampini       }
5962674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
59639162d606SStefano Zampini 
59649162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
59659162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5966984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5967984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5968674ae819SStefano Zampini       if (nnsp_has_cnst) {
59695b08dc53SStefano Zampini         PetscScalar quad_value;
59709162d606SStefano Zampini 
59719162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
59729162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
59739162d606SStefano Zampini 
5974a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5975674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5976a773dcb8SStefano Zampini         } else {
5977a773dcb8SStefano Zampini           quad_value = 1.0;
5978a773dcb8SStefano Zampini         }
5979674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
59809162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5981674ae819SStefano Zampini         }
59829162d606SStefano Zampini         temp_constraints++;
5983674ae819SStefano Zampini         total_counts++;
5984674ae819SStefano Zampini       }
5985674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5986984c4197SStefano Zampini         PetscReal real_value;
59879162d606SStefano Zampini         PetscScalar *ptr_to_data;
59889162d606SStefano Zampini 
5989984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
59909162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5991674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
59929162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5993674ae819SStefano Zampini         }
5994984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5995984c4197SStefano Zampini         /* check if array is null on the connected component */
5996e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
59979162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
599857715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
5999674ae819SStefano Zampini           temp_constraints++;
6000674ae819SStefano Zampini           total_counts++;
60019162d606SStefano Zampini           if (!idxs_copied) {
60029162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
60039162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6004674ae819SStefano Zampini           }
6005674ae819SStefano Zampini         }
60069162d606SStefano Zampini       }
60079162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
600845a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6009eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6010a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
60119162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
60129162d606SStefano Zampini 
60139162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6014a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
60159162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6016a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
60179162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6018a773dcb8SStefano Zampini         } else { /* perform SVD */
60199162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6020674ae819SStefano Zampini 
6021674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6022984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6023984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6024984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6025984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
6026984c4197SStefano Zampini                 from that computed using LAPACKgesvd
6027984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
6028984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
6029984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
6030674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
6031e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6032984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6033674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
6034674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
60359162d606SStefano 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));
6036674ae819SStefano Zampini             }
6037674ae819SStefano Zampini           }
6038e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
6039e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6040e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6041674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6042c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6043674ae819SStefano Zampini #else
6044c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6045674ae819SStefano Zampini #endif
6046674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6047984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6048984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6049674ae819SStefano Zampini           j = 0;
6050984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
6051674ae819SStefano Zampini           total_counts = total_counts-j;
605245a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
6053e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
6054c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6055c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6056c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6057c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6058c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6059c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6060674ae819SStefano Zampini           if (j<temp_constraints) {
6061984c4197SStefano Zampini             PetscInt ii;
6062984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6063674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60649162d606SStefano 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));
6065674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6066984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
6067674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
60689162d606SStefano 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];
6069674ae819SStefano Zampini               }
6070674ae819SStefano Zampini             }
6071674ae819SStefano Zampini           }
6072674ae819SStefano Zampini #else  /* on missing GESVD */
6073e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6074e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6075b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6076674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6077674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
60789162d606SStefano 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));
6079674ae819SStefano Zampini #else
60809162d606SStefano 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));
6081674ae819SStefano Zampini #endif
6082984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6083674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6084984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6085e310c8b4SStefano Zampini           k = temp_constraints;
6086e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
6087674ae819SStefano Zampini           j = 0;
6088e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
608945a1bb75SStefano Zampini           valid_constraints = k-j;
6090911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
6091984c4197SStefano Zampini #endif /* on missing GESVD */
6092674ae819SStefano Zampini         }
6093a773dcb8SStefano Zampini       }
60949162d606SStefano Zampini       /* update pointers information */
60959162d606SStefano Zampini       if (valid_constraints) {
60969162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
60979162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
60989162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
60999162d606SStefano Zampini         /* set change_of_basis flag */
610045a1bb75SStefano Zampini         if (boolforchange) {
6101b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
61029162d606SStefano Zampini         }
6103b3d85658SStefano Zampini         total_counts_cc++;
610445a1bb75SStefano Zampini       }
610545a1bb75SStefano Zampini     }
6106984c4197SStefano Zampini     /* free workspace */
61078f1c130eSStefano Zampini     if (!skip_lapack) {
6108984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6109984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6110984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6111984c4197SStefano Zampini #endif
6112984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6113984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6114984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6115984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6116984c4197SStefano Zampini #endif
6117984c4197SStefano Zampini     }
6118984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6119984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6120984c4197SStefano Zampini     }
6121984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6122cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6123cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6124cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6125cf5a6209SStefano Zampini     }
6126cf5a6209SStefano Zampini     if (n_ISForFaces) {
6127cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6128cf5a6209SStefano Zampini     }
6129cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6130cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6131cf5a6209SStefano Zampini     }
6132cf5a6209SStefano Zampini     if (n_ISForEdges) {
6133cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6134cf5a6209SStefano Zampini     }
6135cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
613608122e43SStefano Zampini   } else {
613708122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6138984c4197SStefano Zampini 
613908122e43SStefano Zampini     total_counts = 0;
614008122e43SStefano Zampini     n_vertices = 0;
6141d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6142d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
614308122e43SStefano Zampini     }
614408122e43SStefano Zampini     max_constraints = 0;
61459162d606SStefano Zampini     total_counts_cc = 0;
614608122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
614708122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
61489162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
614908122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
615008122e43SStefano Zampini     }
61519162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
61529162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
61539162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
61549162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
615574d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
61569162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
61579162d606SStefano Zampini     total_counts_cc = 0;
61589162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
61599162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
61609162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
616108122e43SStefano Zampini       }
616208122e43SStefano Zampini     }
61639162d606SStefano Zampini #if 0
61649162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
61659162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
61669162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
61679162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
61689162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
61699162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
61709162d606SStefano Zampini       }
61719162d606SStefano Zampini       printf("\n");
61729162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
61739162d606SStefano Zampini     }
61741b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
61758bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
61761b968477SStefano Zampini     }
61771b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
61788bec7fa6SStefano 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]);
61791b968477SStefano Zampini     }
618008122e43SStefano Zampini #endif
618108122e43SStefano Zampini 
61828bec7fa6SStefano Zampini     max_size_of_constraint = 0;
61839162d606SStefano 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]);
61849162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
618508122e43SStefano Zampini     /* Change of basis */
6186b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
618708122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
618808122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
618908122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6190b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
619108122e43SStefano Zampini         }
619208122e43SStefano Zampini       }
619308122e43SStefano Zampini     }
619408122e43SStefano Zampini   }
6195984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
61964f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
619708122e43SStefano Zampini 
61989162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
61999162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
6200eee23b56SStefano 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);
6201674ae819SStefano Zampini 
6202674ae819SStefano Zampini   /* Create constraint matrix */
6203674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
620416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6205984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6206984c4197SStefano Zampini 
6207984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6208a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
6209a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
621074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6211984c4197SStefano Zampini   total_primal_vertices=0;
6212b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
62139162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
62149162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
621572b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
62169162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6217b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
621864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
62199162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
62209162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6221a717540cSStefano Zampini       }
6222b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
622391af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6224a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6225a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6226a717540cSStefano Zampini       }
6227fa434743SStefano Zampini     } else {
6228b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6229fa434743SStefano Zampini     }
6230a717540cSStefano Zampini   }
6231b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6232b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6233674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
623470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
62354f1b2e48SStefano 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);
62360e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
62370e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6238984c4197SStefano Zampini 
6239984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
624074d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6241785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6242984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
624374d5cdf7SStefano Zampini 
6244984c4197SStefano Zampini   j = total_primal_vertices;
624574d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6246b3d85658SStefano Zampini   cum = total_primal_vertices;
62479162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
62484641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6249b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6250b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6251b3d85658SStefano Zampini       cum++;
62529162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
625374d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
625474d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
625574d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
625674d5cdf7SStefano Zampini       }
62579162d606SStefano Zampini       j += constraints_n[i];
6258674ae819SStefano Zampini     }
6259674ae819SStefano Zampini   }
6260674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6261674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6262088faed8SStefano Zampini 
6263674ae819SStefano Zampini   /* set values in constraint matrix */
6264984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
62650e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6266674ae819SStefano Zampini   }
6267984c4197SStefano Zampini   total_counts = total_primal_vertices;
62689162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
62694641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
62709162d606SStefano Zampini       PetscInt *cols;
62719162d606SStefano Zampini 
62729162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
62739162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
62749162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
62759162d606SStefano Zampini         PetscInt    row = total_counts+k;
62769162d606SStefano Zampini         PetscScalar *vals;
62779162d606SStefano Zampini 
62789162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
62799162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
62809162d606SStefano Zampini       }
62819162d606SStefano Zampini       total_counts += constraints_n[i];
6282674ae819SStefano Zampini     }
6283674ae819SStefano Zampini   }
6284674ae819SStefano Zampini   /* assembling */
6285674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6286674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
62873272d46bSStefano Zampini   ierr = MatChop(pcbddc->ConstraintMatrix,PETSC_SMALL);CHKERRQ(ierr);
62883272d46bSStefano Zampini   ierr = MatSeqAIJCompress(pcbddc->ConstraintMatrix,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
62893272d46bSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,NULL,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6290088faed8SStefano Zampini 
6291984c4197SStefano Zampini   /*
62926a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6293984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
6294f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
6295984c4197SStefano Zampini   */
6296674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6297674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6298026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6299984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6300984c4197SStefano Zampini     /* working stuff for GEQRF */
630181d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
6302984c4197SStefano Zampini     PetscBLASInt lqr_work;
6303984c4197SStefano Zampini     /* working stuff for UNGQR */
6304984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
6305984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6306984c4197SStefano Zampini     /* working stuff for TRTRS */
6307984c4197SStefano Zampini     PetscScalar  *trs_rhs;
63083f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6309984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6310984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6311984c4197SStefano Zampini     PetscScalar  *start_vals;
6312984c4197SStefano Zampini     /* working stuff for values insertion */
63134641a718SStefano Zampini     PetscBT      is_primal;
631464efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6315906d46d4SStefano Zampini     /* matrix sizes */
6316906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6317906d46d4SStefano Zampini     /* temporary change of basis */
6318906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6319cf5a6209SStefano Zampini     /* extra space for debugging */
6320cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
6321984c4197SStefano Zampini 
6322906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6323906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
632416f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6325bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6326906d46d4SStefano Zampini     /* nonzeros for local mat */
6327bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
63281dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6329bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
63301dd7afcfSStefano Zampini     } else {
63311dd7afcfSStefano Zampini       const PetscInt *ii;
63321dd7afcfSStefano Zampini       PetscInt       n;
63331dd7afcfSStefano Zampini       PetscBool      flg_row;
63341dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
63351dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
63361dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
63371dd7afcfSStefano Zampini     }
63389162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6339a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
63409162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6341a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
63429162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6343a717540cSStefano Zampini         } else {
63449162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
63459162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6346a717540cSStefano Zampini         }
6347a717540cSStefano Zampini       }
6348a717540cSStefano Zampini     }
6349906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6350bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
63511dd7afcfSStefano Zampini     /* Set interior change in the matrix */
63521dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6353bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6354906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6355a717540cSStefano Zampini       }
63561dd7afcfSStefano Zampini     } else {
63571dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
63581dd7afcfSStefano Zampini       PetscScalar    *aa;
63591dd7afcfSStefano Zampini       PetscInt       n;
63601dd7afcfSStefano Zampini       PetscBool      flg_row;
63611dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
63621dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
63631dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
63641dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
63651dd7afcfSStefano Zampini       }
63661dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
63671dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
63681dd7afcfSStefano Zampini     }
6369a717540cSStefano Zampini 
6370a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6371a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6372a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6373a717540cSStefano Zampini     }
6374a717540cSStefano Zampini 
6375a717540cSStefano Zampini 
6376a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6377a717540cSStefano Zampini     /*
6378a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6379a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6380a717540cSStefano Zampini 
6381a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6382a717540cSStefano Zampini 
6383a6b551f4SStefano 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)
6384a6b551f4SStefano Zampini 
6385a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6386a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6387a717540cSStefano Zampini             |              ...                        |
6388a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6389a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6390a717540cSStefano Zampini 
6391a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6392a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6393a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6394a6b551f4SStefano Zampini 
6395a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6396a717540cSStefano Zampini     */
6397a717540cSStefano Zampini     if (qr_needed) {
6398984c4197SStefano Zampini       /* space to store Q */
6399854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
64004e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
64014e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6402984c4197SStefano Zampini       /* first we issue queries for optimal work */
64033f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64043f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
64053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6406984c4197SStefano Zampini       lqr_work = -1;
64073f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6408984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6409984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6410785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6411984c4197SStefano Zampini       lgqr_work = -1;
64123f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64133f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
64143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
64153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
64163f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6417c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6418c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6419984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6420785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6421984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6422785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6423a717540cSStefano Zampini       /* allocating workspace for check */
6424a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6425cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6426a717540cSStefano Zampini       }
6427a717540cSStefano Zampini     }
6428984c4197SStefano Zampini     /* array to store whether a node is primal or not */
64294641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6430473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
64310e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
6432eee23b56SStefano 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);
643339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
643439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
643539e2fb2aSStefano Zampini     }
643639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6437984c4197SStefano Zampini 
6438a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
64399162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
64409162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
64414641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6442984c4197SStefano Zampini         /* get constraint info */
64439162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6444984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6445984c4197SStefano Zampini 
6446984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
64479162d606SStefano 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);
6448674ae819SStefano Zampini         }
6449984c4197SStefano Zampini 
6450fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6451a717540cSStefano Zampini 
6452a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6453a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
64549162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6455a717540cSStefano Zampini           }
6456984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
64579162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6458984c4197SStefano Zampini 
6459984c4197SStefano Zampini           /* compute QR decomposition of constraints */
64603f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
64613f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
64623f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6463674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64643f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6465984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6466674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6467984c4197SStefano Zampini 
6468984c4197SStefano Zampini           /* explictly compute R^-T */
6469984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6470984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
64713f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
64723f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
64733f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
64743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6475984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64763f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6477984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6478984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6479984c4197SStefano Zampini 
6480a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
64813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
64823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
64833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
64843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6485984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6486c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6487c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6488984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6489984c4197SStefano Zampini 
6490984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6491984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6492984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
64933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
64943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
64953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
64963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
64973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
64983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6499984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
65009162d606SStefano 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));
6501984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
65029162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6503984c4197SStefano Zampini 
6504984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
65059162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6506984c4197SStefano Zampini           /* insert cols for primal dofs */
6507984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6508984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
65099162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6510906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6511984c4197SStefano Zampini           }
6512984c4197SStefano Zampini           /* insert cols for dual dofs */
6513984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
65149162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6515984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
65169162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6517906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6518984c4197SStefano Zampini               j++;
6519674ae819SStefano Zampini             }
6520674ae819SStefano Zampini           }
6521984c4197SStefano Zampini 
6522984c4197SStefano Zampini           /* check change of basis */
6523984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6524984c4197SStefano Zampini             PetscInt   ii,jj;
6525984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6526c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6527c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6528c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6529c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6530c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6531c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6532984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6533cf5a6209SStefano 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));
6534984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6535984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6536984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6537cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6538c068d9bbSLisandro 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;
6539674ae819SStefano Zampini               }
6540674ae819SStefano Zampini             }
6541984c4197SStefano Zampini             if (!valid_qr) {
654222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6543984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6544984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6545cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6546cf5a6209SStefano 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]));
6547674ae819SStefano Zampini                   }
6548c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
6549cf5a6209SStefano 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]));
6550984c4197SStefano Zampini                   }
6551984c4197SStefano Zampini                 }
6552984c4197SStefano Zampini               }
6553674ae819SStefano Zampini             } else {
655422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6555674ae819SStefano Zampini             }
6556674ae819SStefano Zampini           }
6557a717540cSStefano Zampini         } else { /* simple transformation block */
6558a717540cSStefano Zampini           PetscInt    row,col;
6559a6b551f4SStefano Zampini           PetscScalar val,norm;
6560a6b551f4SStefano Zampini 
6561a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
65629162d606SStefano 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));
6563a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
65649162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
65659162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6566bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
65679162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6568906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
65699162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6570a717540cSStefano Zampini             } else {
6571a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
65729162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6573a717540cSStefano Zampini                 if (row != col) {
65749162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6575a717540cSStefano Zampini                 } else {
65769162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6577a717540cSStefano Zampini                 }
6578906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6579a717540cSStefano Zampini               }
6580a717540cSStefano Zampini             }
6581a717540cSStefano Zampini           }
658298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
658322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6584a717540cSStefano Zampini           }
6585674ae819SStefano Zampini         }
6586984c4197SStefano Zampini       } else {
6587984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
65889162d606SStefano 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);
6589674ae819SStefano Zampini         }
6590674ae819SStefano Zampini       }
6591674ae819SStefano Zampini     }
6592a717540cSStefano Zampini 
6593a717540cSStefano Zampini     /* free workspace */
6594a717540cSStefano Zampini     if (qr_needed) {
6595984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6596cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6597984c4197SStefano Zampini       }
6598984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6599984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6600984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6601984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6602984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6603674ae819SStefano Zampini     }
6604a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6605906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6606906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6607906d46d4SStefano Zampini 
6608906d46d4SStefano Zampini     /* assembling of global change of variable */
660988c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6610bbb9e6c6SStefano Zampini       Mat      tmat;
661116f15bc4SStefano Zampini       PetscInt bs;
661216f15bc4SStefano Zampini 
6613906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6614906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6615bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6616bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6617*487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6618*487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6619bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6620bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
662116f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
662216f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6623906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6624bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6625*487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6626bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6627bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6628bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6629e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6630e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6631bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6632bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
663388c03ad3SStefano Zampini 
6634906d46d4SStefano Zampini       /* check */
6635906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6636906d46d4SStefano Zampini         PetscReal error;
6637906d46d4SStefano Zampini         Vec       x,x_change;
6638906d46d4SStefano Zampini 
6639906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6640906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6641906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6642906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6643e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6644e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6645bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6646e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6647e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6648906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6649906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6650906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6651637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6652637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6653637e8532SStefano Zampini         }
6654906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6655906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6656906d46d4SStefano Zampini       }
6657b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6658b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6659b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6660bf3a8328SStefano Zampini 
666113903a91SSatish 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");
6662b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6663ac632422SStefano Zampini           Mat                    S_new,tmat;
6664bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6665bbb9e6c6SStefano Zampini 
6666bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
66677dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6668bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6669bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6670bf3a8328SStefano Zampini             IS                     is_V;
6671b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6672b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6673b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6674b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6675b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6676bf3a8328SStefano Zampini           }
6677bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6678ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6679b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6680ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6681bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6682bf3a8328SStefano Zampini             const PetscScalar *array;
6683bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6684bf3a8328SStefano Zampini             PetscInt          i,n_V;
6685bf3a8328SStefano Zampini 
6686b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6687b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6688b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6689b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6690b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6691b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6692b087196eSStefano Zampini               PetscScalar val;
6693b087196eSStefano Zampini               PetscInt    idx;
6694b087196eSStefano Zampini 
6695b087196eSStefano Zampini               idx = idxs_V[i];
6696b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6697b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6698b087196eSStefano Zampini             }
6699b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6700b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6701bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6702bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6703bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6704bf3a8328SStefano Zampini           }
6705ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6706ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6707ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6708ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6709b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6710ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6711bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6712b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6713bf3a8328SStefano Zampini             }
6714ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6715ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6716ac632422SStefano Zampini           }
6717b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
671888c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6719b96c3477SStefano Zampini         }
6720c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6721b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6722c9db6a07SStefano Zampini           PetscInt i;
6723c9db6a07SStefano Zampini 
6724c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6725c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6726c9db6a07SStefano Zampini           }
6727c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6728c9db6a07SStefano Zampini         }
6729b96c3477SStefano Zampini       }
673016909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
673116909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
673216909a7fSStefano Zampini       } else {
6733906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
673416909a7fSStefano Zampini       }
67351dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
673627b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
673772b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
673872b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
673972b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
674072b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
674172b8c272SStefano Zampini     }
67421dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
674327b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6744b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6745b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6746906d46d4SStefano Zampini     } else {
67471dd7afcfSStefano Zampini       Mat benign_global = NULL;
674827b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
67491dd7afcfSStefano Zampini         Mat tmat;
67501dd7afcfSStefano Zampini 
67511dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
67521dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
67531dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
67541dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
67551dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
67561dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
67571dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
67581dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
67591dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
67601dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
67611dd7afcfSStefano Zampini           Mat M;
67621dd7afcfSStefano Zampini 
67631dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
67641dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
67651dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
67661dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6767906d46d4SStefano Zampini         } else {
67681dd7afcfSStefano Zampini           Mat         eye;
67691dd7afcfSStefano Zampini           PetscScalar *array;
67701dd7afcfSStefano Zampini 
67711dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
67721dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
67731dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
67741dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6775906d46d4SStefano Zampini           }
67761dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
67771dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67781dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67791dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
67801dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
67811dd7afcfSStefano Zampini         }
6782*487b449aSStefano Zampini         ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6783*487b449aSStefano Zampini         ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6784*487b449aSStefano Zampini         ierr = MatConvert(tmat,MATAIJ,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
67851dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
67861dd7afcfSStefano Zampini       }
67871dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
67881dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
67891dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
679027b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
67911dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
67921dd7afcfSStefano Zampini       }
67931dd7afcfSStefano Zampini     }
679416909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
679516909a7fSStefano Zampini       IS             is_global;
679616909a7fSStefano Zampini       const PetscInt *gidxs;
679716909a7fSStefano Zampini 
679816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
679916909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
680016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
68017dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
680216909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
680316909a7fSStefano Zampini     }
68041dd7afcfSStefano Zampini   }
68051dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
68061dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6807b9b85e73SStefano Zampini   }
6808a717540cSStefano Zampini 
680972b8c272SStefano Zampini   if (!pcbddc->fake_change) {
68104f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
68114f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
68124f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
68134f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6814019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6815019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6816019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6817019a44ceSStefano Zampini     }
6818019a44ceSStefano Zampini 
6819019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6820727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6821727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
68229f47a83aSStefano 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);
6823c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
68240e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
68259f47a83aSStefano 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);
6826727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6827727cdba6SStefano Zampini       }
68280e6343abSStefano Zampini     }
6829727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6830b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
683172b8c272SStefano Zampini   }
683272b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6833727cdba6SStefano Zampini 
6834a717540cSStefano Zampini   /* flush dbg viewer */
6835b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6836b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6837b8ffe317SStefano Zampini   }
6838a717540cSStefano Zampini 
6839e310c8b4SStefano Zampini   /* free workspace */
6840a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
68414641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
684208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
68439162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
68449162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
684508122e43SStefano Zampini   } else {
68469162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
68479162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
68489162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
684908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
685008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
68519162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
68529162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
685308122e43SStefano Zampini   }
6854674ae819SStefano Zampini   PetscFunctionReturn(0);
6855674ae819SStefano Zampini }
685604a6f24aSStefano Zampini /* #undef PETSC_MISSING_LAPACK_GESVD */
6857674ae819SStefano Zampini 
6858674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6859674ae819SStefano Zampini {
686071582508SStefano Zampini   ISLocalToGlobalMapping map;
6861674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6862674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
686366da6bd7Sstefano_zampini   PetscInt               i,N;
686466da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
686566da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6866674ae819SStefano Zampini 
6867674ae819SStefano Zampini   PetscFunctionBegin;
68688af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6869b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
68708e61c736SStefano Zampini     /* Reset previously computed graph */
68718e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6872674ae819SStefano Zampini     /* Init local Graph struct */
68737fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
687471582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6875be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6876674ae819SStefano Zampini 
68777a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
68787a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
68797a0e7b2cSstefano_zampini     }
6880575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
6881ab8c8b98SStefano 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);
68829577ea80SStefano Zampini 
6883674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
688466da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
68854d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
68864d379d7bSStefano Zampini       PetscInt  nvtxs;
6887e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6888674ae819SStefano Zampini 
68892fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
68902fffb893SStefano Zampini       if (flg_row) {
68914d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6892b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
68932fffb893SStefano Zampini       }
68942fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
689566da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6896674ae819SStefano Zampini     }
68979b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
68989b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6899674ae819SStefano Zampini     }
6900674ae819SStefano Zampini 
6901ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
6902ab8c8b98SStefano Zampini       PetscReal    *lcoords;
6903ab8c8b98SStefano Zampini       PetscInt     n;
6904ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
6905ab8c8b98SStefano Zampini 
6906ab8c8b98SStefano Zampini       if (pcbddc->mat_graph->cnloc != pc->pmat->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local coordinates! Got %D, expected %D",pcbddc->mat_graph->cnloc,pc->pmat->rmap->n);
6907ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
6908ab8c8b98SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
6909ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
6910ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
6911ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
6912ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6913ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6914ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
6915ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
6916ab8c8b98SStefano Zampini 
6917ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
6918ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
6919ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
6920ab8c8b98SStefano Zampini     }
6921ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cnloc && pcbddc->mat_graph->cnloc != pcbddc->mat_graph->nvtxs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local subdomain coordinates! Got %D, expected %D",pcbddc->mat_graph->cnloc,pcbddc->mat_graph->nvtxs);
69221c7a958bSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && !pcbddc->corner_selected);
6923ab8c8b98SStefano Zampini 
6924674ae819SStefano Zampini     /* Setup of Graph */
69254b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
692614f95afaSStefano 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);
6927674ae819SStefano Zampini 
69284f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
69294f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
69304f1b2e48SStefano Zampini       PetscInt *local_subs;
69314f1b2e48SStefano Zampini 
69324f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
69334f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
69344f1b2e48SStefano Zampini         const PetscInt *idxs;
69354f1b2e48SStefano Zampini         PetscInt       nl,j;
69364f1b2e48SStefano Zampini 
69374f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
69384f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
693971582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
69404f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
69414f1b2e48SStefano Zampini       }
69424f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
69434f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
69444f1b2e48SStefano Zampini     }
69458af8fcf9SStefano Zampini   }
69464f1b2e48SStefano Zampini 
6947cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6948674ae819SStefano Zampini     /* Graph's connected components analysis */
6949674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
695071582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
69518af8fcf9SStefano Zampini   }
695266da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6953674ae819SStefano Zampini   PetscFunctionReturn(0);
6954674ae819SStefano Zampini }
6955674ae819SStefano Zampini 
69569a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
69579a7d3425SStefano Zampini {
69589a7d3425SStefano Zampini   PetscInt       i,j;
69599a7d3425SStefano Zampini   PetscScalar    *alphas;
69609a7d3425SStefano Zampini   PetscErrorCode ierr;
69619a7d3425SStefano Zampini 
69629a7d3425SStefano Zampini   PetscFunctionBegin;
69638c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
6964785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
69658c0031efSStefano Zampini   ierr = VecNormalize(vecs[0],NULL);CHKERRQ(ierr);
69668c0031efSStefano Zampini   for (i=1;i<n;i++) {
69678c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
69688c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
69698c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
69709a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
69719a7d3425SStefano Zampini   }
69729a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
69739a7d3425SStefano Zampini   PetscFunctionReturn(0);
69749a7d3425SStefano Zampini }
69759a7d3425SStefano Zampini 
6976bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6977e7931f94SStefano Zampini {
697857de7509SStefano Zampini   Mat            A;
6979e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6980e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
698152e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
698252e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6983bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
698457de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
698527b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
698627b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
698727b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
698827b6a85dSStefano Zampini   MPI_Comm       subcomm;
698952e5ac9dSStefano Zampini   PetscErrorCode ierr;
6990a57a6d2fSStefano Zampini 
6991e7931f94SStefano Zampini   PetscFunctionBegin;
699257de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
699357de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6994fbfcfee5SBarry 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);
699557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
699657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
699757de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
699857de7509SStefano Zampini 
699957de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
700057de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
700157de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
700257de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
700357de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
7004bb360cb4SStefano Zampini   im_active = !!n;
700557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
700657de7509SStefano Zampini   void_procs = size - active_procs;
700757de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
700857de7509SStefano Zampini   if (void_procs) {
700957de7509SStefano Zampini     PetscInt ncand;
701057de7509SStefano Zampini 
701157de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
701257de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
701357de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
701457de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
701557de7509SStefano Zampini       if (!procs_candidates[i]) {
701657de7509SStefano Zampini         procs_candidates[ncand++] = i;
701757de7509SStefano Zampini       }
701857de7509SStefano Zampini     }
701957de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
702057de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
702157de7509SStefano Zampini   }
702257de7509SStefano Zampini 
7023bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
702414f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
7025bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7026bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
702714f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
702814f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
702914f0bfb9SStefano Zampini     else dest = rank;
703057de7509SStefano Zampini     if (im_active) {
703157de7509SStefano Zampini       issize = 1;
703257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
703314f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
703457de7509SStefano Zampini       } else {
703514f0bfb9SStefano Zampini         isidx = dest;
703657de7509SStefano Zampini       }
703757de7509SStefano Zampini     } else {
703857de7509SStefano Zampini       issize = 0;
703957de7509SStefano Zampini       isidx = -1;
704057de7509SStefano Zampini     }
7041bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
704257de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7043daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
704457de7509SStefano Zampini     PetscFunctionReturn(0);
704557de7509SStefano Zampini   }
7046c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7047c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
704827b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7049e7931f94SStefano Zampini 
7050e7931f94SStefano Zampini   /* Get info on mapping */
70513bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7052e7931f94SStefano Zampini 
7053e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7054785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7055e7931f94SStefano Zampini   xadj[0] = 0;
7056e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7057785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7058785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7059bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
706027b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
706127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
706227b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7063e7931f94SStefano Zampini 
706427b6a85dSStefano Zampini   xadj_count = 0;
70652b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
706627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
706727b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7068d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7069d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7070d023bfaeSStefano Zampini         xadj_count++;
707127b6a85dSStefano Zampini         break;
707227b6a85dSStefano Zampini       }
7073e7931f94SStefano Zampini     }
7074e7931f94SStefano Zampini   }
7075d023bfaeSStefano Zampini   xadj[1] = xadj_count;
707627b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
70773bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7078e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7079e7931f94SStefano Zampini 
70803837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7081e7931f94SStefano Zampini 
708227b6a85dSStefano Zampini   /* Restrict work on active processes only */
708327b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
708427b6a85dSStefano Zampini   if (void_procs) {
708527b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
708627b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
708727b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
708827b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
708927b6a85dSStefano Zampini   } else {
709027b6a85dSStefano Zampini     psubcomm = NULL;
709127b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
709227b6a85dSStefano Zampini   }
709327b6a85dSStefano Zampini 
709427b6a85dSStefano Zampini   v_wgt = NULL;
709527b6a85dSStefano Zampini   if (!color) {
7096e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7097e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7098e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7099c8587f34SStefano Zampini   } else {
710052e5ac9dSStefano Zampini     Mat             subdomain_adj;
710152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
710252e5ac9dSStefano Zampini     MatPartitioning partitioner;
710327b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
710452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
710557de7509SStefano Zampini     PetscMPIInt     size;
7106b0c7d250SStefano Zampini     PetscBool       aggregate;
7107b0c7d250SStefano Zampini 
710827b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
710927b6a85dSStefano Zampini     if (void_procs) {
711027b6a85dSStefano Zampini       PetscInt prank = rank;
7111785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
711227b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
7113e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7114e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7115c8587f34SStefano Zampini       }
7116e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
711727b6a85dSStefano Zampini     } else {
711827b6a85dSStefano Zampini       oldranks = NULL;
711927b6a85dSStefano Zampini     }
7120b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
712127b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7122b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7123b0c7d250SStefano Zampini       PetscMPIInt nrank;
7124b0c7d250SStefano Zampini       PetscScalar *vals;
7125b0c7d250SStefano Zampini 
712627b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7127b0c7d250SStefano Zampini       lrows = 0;
7128b0c7d250SStefano Zampini       if (nrank<redprocs) {
7129b0c7d250SStefano Zampini         lrows = size/redprocs;
7130b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7131b0c7d250SStefano Zampini       }
713227b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7133b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7134b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7135b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7136b0c7d250SStefano Zampini       row = nrank;
7137b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7138b0c7d250SStefano Zampini       cols = adjncy;
7139b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7140b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7141b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7142b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7143b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
714452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
714552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
714652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7147b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
714827b6a85dSStefano Zampini       if (use_vwgt) {
714927b6a85dSStefano Zampini         Vec               v;
715027b6a85dSStefano Zampini         const PetscScalar *array;
715127b6a85dSStefano Zampini         PetscInt          nl;
715227b6a85dSStefano Zampini 
715327b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7154bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
715527b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
715627b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
715727b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
715827b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
715927b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
716022db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
716127b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
716227b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
716327b6a85dSStefano Zampini       }
7164b0c7d250SStefano Zampini     } else {
716527b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
716627b6a85dSStefano Zampini       if (use_vwgt) {
716727b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7168bb360cb4SStefano Zampini         v_wgt[0] = n;
716927b6a85dSStefano Zampini       }
7170b0c7d250SStefano Zampini     }
717122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7172e7931f94SStefano Zampini 
7173e7931f94SStefano Zampini     /* Partition */
717427b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7175e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
717627b6a85dSStefano Zampini     if (v_wgt) {
7177e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7178c8587f34SStefano Zampini     }
717957de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
718057de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7181e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7182e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
718322b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7184e7931f94SStefano Zampini 
718552e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
71866583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
718752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
718852e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
718957de7509SStefano Zampini     if (!aggregate) {
719057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
719127b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
719227b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
719327b6a85dSStefano Zampini #endif
719457de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
719527b6a85dSStefano Zampini       } else if (oldranks) {
7196b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
719727b6a85dSStefano Zampini       } else {
719827b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
719957de7509SStefano Zampini       }
720028143c3dSStefano Zampini     } else {
72017fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7202b0c7d250SStefano Zampini       PetscMPIInt tag;
7203b0c7d250SStefano Zampini       MPI_Request *reqs;
7204b0c7d250SStefano Zampini 
7205b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7206b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7207b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
720827b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
720928143c3dSStefano Zampini       }
72107fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7211b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7212b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
721357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
721427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
721527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
721627b6a85dSStefano Zampini #endif
72177fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
721827b6a85dSStefano Zampini       } else if (oldranks) {
72197fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
722027b6a85dSStefano Zampini       } else {
72217fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7222e7931f94SStefano Zampini       }
722357de7509SStefano Zampini     }
722452e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7225e7931f94SStefano Zampini     /* clean up */
7226e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
722752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7228e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7229e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7230e7931f94SStefano Zampini   }
723127b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
723257de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7233e7931f94SStefano Zampini 
7234e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7235e7931f94SStefano Zampini   i = 1;
723627b6a85dSStefano Zampini   if (!color) i=0;
723757de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7238e7931f94SStefano Zampini   PetscFunctionReturn(0);
7239e7931f94SStefano Zampini }
7240e7931f94SStefano Zampini 
7241e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7242e7931f94SStefano Zampini 
72431e0482f5SStefano 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[])
7244e7931f94SStefano Zampini {
724570cf5478SStefano Zampini   Mat                    local_mat;
7246e7931f94SStefano Zampini   IS                     is_sends_internal;
72479d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
72481ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
72499d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7250e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7251e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7252e7931f94SStefano Zampini   const PetscInt*        is_indices;
7253e7931f94SStefano Zampini   MatType                new_local_type;
7254e7931f94SStefano Zampini   /* buffers */
7255e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
725628143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
72579d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
7258e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
72591ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7260e7931f94SStefano Zampini   /* MPI */
726128143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
726228143c3dSStefano Zampini   PetscSubcomm           subcomm;
7263e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
726428143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
726528143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
72661ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
72671ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
72681ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7269e7931f94SStefano Zampini   PetscErrorCode         ierr;
7270e7931f94SStefano Zampini 
7271e7931f94SStefano Zampini   PetscFunctionBegin;
727257de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7273e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7274fbfcfee5SBarry 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);
727557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
727657de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
727757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
727857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
727957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
72801ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
72811ae86dd6SStefano Zampini   if (nvecs) {
72821ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
72831ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
72841ae86dd6SStefano Zampini   }
728557de7509SStefano Zampini   /* further checks */
7286e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7287e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7288e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7289e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7290e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
729157de7509SStefano Zampini   if (reuse && *mat_n) {
729270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
729357de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
729470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
729528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
729670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
729770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
729870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
729970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
730070cf5478SStefano Zampini   }
7301e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7302e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
730357de7509SStefano Zampini 
7304e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7305e7931f94SStefano Zampini   if (!is_sends) {
730628143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7307bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7308c8587f34SStefano Zampini   } else {
7309e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7310e7931f94SStefano Zampini     is_sends_internal = is_sends;
7311c8587f34SStefano Zampini   }
7312e7931f94SStefano Zampini 
7313e7931f94SStefano Zampini   /* get comm */
7314a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7315e7931f94SStefano Zampini 
7316e7931f94SStefano Zampini   /* compute number of sends */
7317e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7318e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7319e7931f94SStefano Zampini 
7320e7931f94SStefano Zampini   /* compute number of receives */
7321e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
7322785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
7323e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
7324e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7325e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7326e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7327e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7328e7931f94SStefano Zampini 
732928143c3dSStefano Zampini   /* restrict comm if requested */
733028143c3dSStefano Zampini   subcomm = 0;
733128143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
733228143c3dSStefano Zampini   if (restrict_comm) {
7333779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7334779c1cceSStefano Zampini 
733528143c3dSStefano Zampini     color = 0;
733653a05cb3SStefano Zampini     if (restrict_full) {
733753a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
733853a05cb3SStefano Zampini     } else {
733953a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
734053a05cb3SStefano Zampini     }
7341b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
734228143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
734328143c3dSStefano Zampini     /* check if reuse has been requested */
734457de7509SStefano Zampini     if (reuse) {
734528143c3dSStefano Zampini       if (*mat_n) {
734628143c3dSStefano Zampini         PetscMPIInt subcommsize2;
734728143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
734828143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
734928143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
735028143c3dSStefano Zampini       } else {
735128143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
735228143c3dSStefano Zampini       }
735328143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7354779c1cceSStefano Zampini       PetscMPIInt rank;
7355779c1cceSStefano Zampini 
7356779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
735728143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
735828143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
735928143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7360306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
736128143c3dSStefano Zampini     }
736228143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
736328143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
736428143c3dSStefano Zampini   } else {
736528143c3dSStefano Zampini     comm_n = comm;
736628143c3dSStefano Zampini   }
736728143c3dSStefano Zampini 
7368e7931f94SStefano Zampini   /* prepare send/receive buffers */
7369785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
7370e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7371785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
7372e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
737328143c3dSStefano Zampini   if (nis) {
7374854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
737528143c3dSStefano Zampini   }
7376e7931f94SStefano Zampini 
737728143c3dSStefano Zampini   /* Get data from local matrices */
73786c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7379e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7380e7931f94SStefano Zampini     /*
7381e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7382e7931f94SStefano Zampini        send_buffer_idxs should contain:
7383e7931f94SStefano Zampini        - MatType_PRIVATE type
7384e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7385e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7386e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7387e7931f94SStefano Zampini     */
73886c4ed002SBarry Smith   else {
7389e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
73903bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7391854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7392e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7393e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
73943bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7395e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
73963bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7397e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7398e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7399e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7400e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7401c8587f34SStefano Zampini     }
7402c8587f34SStefano Zampini   }
7403e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
740428143c3dSStefano Zampini   /* additional is (if any) */
740528143c3dSStefano Zampini   if (nis) {
740628143c3dSStefano Zampini     PetscMPIInt psum;
740728143c3dSStefano Zampini     PetscInt j;
740828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
740928143c3dSStefano Zampini       PetscInt plen;
741028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
741128143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
741228143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
741328143c3dSStefano Zampini     }
7414854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
741528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
741628143c3dSStefano Zampini       PetscInt plen;
741728143c3dSStefano Zampini       const PetscInt *is_array_idxs;
741828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
741928143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
742028143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
742128143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
742228143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
742328143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
742428143c3dSStefano Zampini     }
742528143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
742628143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
742728143c3dSStefano Zampini     }
742828143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
742928143c3dSStefano Zampini   }
74303b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
743128143c3dSStefano Zampini 
7432e7931f94SStefano Zampini   buf_size_idxs = 0;
7433e7931f94SStefano Zampini   buf_size_vals = 0;
743428143c3dSStefano Zampini   buf_size_idxs_is = 0;
74351ae86dd6SStefano Zampini   buf_size_vecs = 0;
7436e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7437e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7438e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
743928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
74401ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7441e7931f94SStefano Zampini   }
7442785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7443785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
744495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
74451ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7446e7931f94SStefano Zampini 
7447e7931f94SStefano Zampini   /* get new tags for clean communications */
7448e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7449e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
745028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
74511ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7452e7931f94SStefano Zampini 
7453e7931f94SStefano Zampini   /* allocate for requests */
7454785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7455785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
745695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
74571ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7458785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7459785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
746095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
74611ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7462e7931f94SStefano Zampini 
7463e7931f94SStefano Zampini   /* communications */
7464e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7465e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
746628143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
74671ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7468e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7469e7931f94SStefano Zampini     source_dest = onodes[i];
7470e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7471e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7472e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7473e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
747428143c3dSStefano Zampini     if (nis) {
747557de7509SStefano Zampini       source_dest = onodes_is[i];
747628143c3dSStefano 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);
747728143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
747828143c3dSStefano Zampini     }
74791ae86dd6SStefano Zampini     if (nvecs) {
74801ae86dd6SStefano Zampini       source_dest = onodes[i];
74811ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
74821ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
74831ae86dd6SStefano Zampini     }
7484e7931f94SStefano Zampini   }
7485e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7486e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7487e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7488e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
748928143c3dSStefano Zampini     if (nis) {
749028143c3dSStefano 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);
749128143c3dSStefano Zampini     }
74921ae86dd6SStefano Zampini     if (nvecs) {
74931ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74941ae86dd6SStefano 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);
74951ae86dd6SStefano Zampini     }
7496e7931f94SStefano Zampini   }
7497e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7498e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7499e7931f94SStefano Zampini 
7500e7931f94SStefano Zampini   /* assemble new l2g map */
7501e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7502e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
75039d30be91SStefano Zampini   new_local_rows = 0;
7504e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
75059d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7506e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7507e7931f94SStefano Zampini   }
75089d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7509e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
75109d30be91SStefano Zampini   new_local_rows = 0;
7511e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
75129d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
75139d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7514e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7515e7931f94SStefano Zampini   }
75169d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
75179d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7518e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7519e7931f94SStefano Zampini 
7520e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7521e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7522e7931f94SStefano 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) */
7523e7931f94SStefano Zampini   if (n_recvs) {
752428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7525e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7526e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7527e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7528e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7529e7931f94SStefano Zampini         break;
7530e7931f94SStefano Zampini       }
7531e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7532e7931f94SStefano Zampini     }
7533e7931f94SStefano Zampini     switch (new_local_type_private) {
753428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7535e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7536e7931f94SStefano Zampini         bs = 1;
7537e7931f94SStefano Zampini         break;
7538e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7539e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7540e7931f94SStefano Zampini         bs = 1;
7541e7931f94SStefano Zampini         break;
7542e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7543e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7544e7931f94SStefano Zampini         break;
7545e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7546e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7547e7931f94SStefano Zampini         break;
7548e7931f94SStefano Zampini       default:
7549fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7550e7931f94SStefano Zampini         break;
7551e7931f94SStefano Zampini     }
7552ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7553ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
755428143c3dSStefano Zampini     bs = 1;
7555e7931f94SStefano Zampini   }
7556e7931f94SStefano Zampini 
755770cf5478SStefano Zampini   /* create MATIS object if needed */
755857de7509SStefano Zampini   if (!reuse) {
7559e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7560e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
756170cf5478SStefano Zampini   } else {
756270cf5478SStefano Zampini     /* it also destroys the local matrices */
756357de7509SStefano Zampini     if (*mat_n) {
756470cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
756557de7509SStefano Zampini     } else { /* this is a fake object */
756657de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
756757de7509SStefano Zampini     }
756870cf5478SStefano Zampini   }
756970cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7570e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
75719d30be91SStefano Zampini 
75729d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
75739d30be91SStefano Zampini 
75749d30be91SStefano Zampini   /* Global to local map of received indices */
75759d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
75769d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
75779d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
75789d30be91SStefano Zampini 
75799d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
75809d30be91SStefano Zampini   buf_size_idxs = 0;
75819d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
75829d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
75839d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
75849d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
75859d30be91SStefano Zampini   }
75869d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
75879d30be91SStefano Zampini 
75889d30be91SStefano Zampini   /* set preallocation */
75899d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
75909d30be91SStefano Zampini   if (!newisdense) {
75919d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
75929d30be91SStefano Zampini 
75939d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
75949d30be91SStefano Zampini     if (n_recvs) {
75959d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
75969d30be91SStefano Zampini     }
75979d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
75989d30be91SStefano Zampini       PetscInt j;
75999d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
76009d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
76019d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
76029d30be91SStefano Zampini         }
76039d30be91SStefano Zampini       } else {
76049d30be91SStefano Zampini         /* TODO */
76059d30be91SStefano Zampini       }
76069d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
76079d30be91SStefano Zampini     }
76089d30be91SStefano Zampini     if (new_local_nnz) {
76099d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
76109d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
76119d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
76129d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76139d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
76149d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76159d30be91SStefano Zampini     } else {
76169d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76179d30be91SStefano Zampini     }
76189d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
76199d30be91SStefano Zampini   } else {
76209d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76219d30be91SStefano Zampini   }
7622e7931f94SStefano Zampini 
7623e7931f94SStefano Zampini   /* set values */
7624e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
76259d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7626e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7627e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7628e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
76299d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7630e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7631e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7632e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
763328143c3dSStefano Zampini     } else {
763428143c3dSStefano Zampini       /* TODO */
7635e7931f94SStefano Zampini     }
7636e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7637e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7638e7931f94SStefano Zampini   }
7639e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7640e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76413b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
764270cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
764370cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76449d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7645e7931f94SStefano Zampini 
7646dfd14d43SStefano Zampini #if 0
764728143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7648e7931f94SStefano Zampini     Vec       lvec,rvec;
7649e7931f94SStefano Zampini     PetscReal infty_error;
7650e7931f94SStefano Zampini 
76512a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7652e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7653e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7654e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
765570cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7656e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7657e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7658e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7659e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7660e7931f94SStefano Zampini   }
766128143c3dSStefano Zampini #endif
7662e7931f94SStefano Zampini 
766328143c3dSStefano Zampini   /* assemble new additional is (if any) */
766428143c3dSStefano Zampini   if (nis) {
766528143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
766628143c3dSStefano Zampini 
766728143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7668854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
766928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
767028143c3dSStefano Zampini     psum = 0;
767128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
767228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
767328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
767428143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
767528143c3dSStefano Zampini         psum += plen;
767628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
767728143c3dSStefano Zampini       }
767828143c3dSStefano Zampini     }
7679854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7680854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
768128143c3dSStefano Zampini     for (i=1;i<nis;i++) {
768228143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
768328143c3dSStefano Zampini     }
768428143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
768528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
768628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
768728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
768828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
768928143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
769028143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
769128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
769228143c3dSStefano Zampini       }
769328143c3dSStefano Zampini     }
769428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
769528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
769628143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
769728143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
769828143c3dSStefano Zampini     }
769928143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
770028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
770128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
770228143c3dSStefano Zampini   }
7703e7931f94SStefano Zampini   /* free workspace */
770428143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7705e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7706e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7707e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7708e7931f94SStefano Zampini   if (isdense) {
7709e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7710e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
77113b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7712e7931f94SStefano Zampini   } else {
7713e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7714e7931f94SStefano Zampini   }
771528143c3dSStefano Zampini   if (nis) {
771628143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
771728143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
771828143c3dSStefano Zampini   }
77191ae86dd6SStefano Zampini 
77201ae86dd6SStefano Zampini   if (nvecs) {
77211ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77221ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77231ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77241ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
77251ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
77261ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
77271ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
77281ae86dd6SStefano Zampini     /* set values */
77291ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
77301ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
77311ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77321ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
77331ae86dd6SStefano Zampini       PetscInt j;
77341ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
77351ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
77361ae86dd6SStefano Zampini       }
77371ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
77381ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
77391ae86dd6SStefano Zampini     }
77401ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77411ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
77421ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
77431ae86dd6SStefano Zampini   }
77441ae86dd6SStefano Zampini 
77451ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
77461ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7747e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7748e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
77491ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
775028143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7751e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7752e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
77531ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
775428143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7755e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7756e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7757e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7758e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7759e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
776028143c3dSStefano Zampini   if (nis) {
776128143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
776228143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
776328143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
776428143c3dSStefano Zampini   }
776528143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
776628143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
776728143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
776828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
776928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
777028143c3dSStefano Zampini     }
77711ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
77721ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
77731ae86dd6SStefano Zampini     }
777453a05cb3SStefano Zampini     *mat_n = NULL;
777528143c3dSStefano Zampini   }
7776e7931f94SStefano Zampini   PetscFunctionReturn(0);
7777e7931f94SStefano Zampini }
7778a57a6d2fSStefano Zampini 
777912edc857SStefano Zampini /* temporary hack into ksp private data structure */
7780af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
778112edc857SStefano Zampini 
7782c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7783c8587f34SStefano Zampini {
7784c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7785c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
778620a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
77871ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
77881e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
77899881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
779020a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
77916e683305SStefano Zampini   IS                     coarse_is,*isarray;
77926e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
779330368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7794f9eb5b7dSStefano Zampini   PC                     pc_temp;
7795c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7796c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7797f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
77987274672aSStefano Zampini   PetscBool              coarse_reuse;
77991e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
780068457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
780122bc73bbSStefano Zampini   PetscScalar            *array;
780257de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
780357de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
78047de4f681Sstefano_zampini   PetscMPIInt            commsize;
78059881197aSStefano Zampini   PetscErrorCode         ierr;
7806fdc09c96SStefano Zampini 
7807c8587f34SStefano Zampini   PetscFunctionBegin;
7808c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
780968457ee5SStefano 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 */
7810fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
78115a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
78127de4f681Sstefano_zampini 
78137de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7814fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7815f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7816f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7817f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7818fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
781951bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
782051bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7821727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7822fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7823fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7824fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7825f4ddd8eeSStefano Zampini       }
7826fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7827fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7828f4ddd8eeSStefano Zampini     }
782970cf5478SStefano Zampini     /* reset any subassembling information */
783057de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
783170cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
783257de7509SStefano Zampini     }
78336e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7834fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7835f4ddd8eeSStefano Zampini   }
783657de7509SStefano Zampini   /* assemble coarse matrix */
783757de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
783857de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
783957de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
784057de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
784118a45a71SStefano Zampini   } else {
784257de7509SStefano Zampini     coarse_mat = NULL;
784357de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
78446e683305SStefano Zampini   }
7845e7931f94SStefano Zampini 
7846abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7847abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7848abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7849abbbba34SStefano Zampini 
7850abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
785122bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
785222bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
785322bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
785422bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7855e176bc59SStefano 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);
78566e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
78576e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78586e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7859abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7860abbbba34SStefano Zampini 
786157de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
786257de7509SStefano Zampini   im_active = !!(pcis->n);
786357de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
786457de7509SStefano Zampini 
786514f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
786657de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
786757de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
78687de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
786957de7509SStefano Zampini   coarse_mat_is = NULL;
787057de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
787157de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
78721ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
787357de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
787457de7509SStefano Zampini   if (multilevel_requested) {
787557de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
787657de7509SStefano Zampini     restr = PETSC_FALSE;
787757de7509SStefano Zampini     full_restr = PETSC_FALSE;
787857de7509SStefano Zampini   } else {
787957de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
788057de7509SStefano Zampini     restr = PETSC_TRUE;
788157de7509SStefano Zampini     full_restr = PETSC_TRUE;
788257de7509SStefano Zampini   }
78837de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
788457de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
788557de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7886a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7887bb360cb4SStefano Zampini       if (multilevel_requested) {
7888bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7889bb360cb4SStefano Zampini       } else {
7890bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7891bb360cb4SStefano Zampini       }
7892a198735bSStefano Zampini     } else {
78937de4f681Sstefano_zampini       PetscMPIInt rank;
7894a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
78957de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7896a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7897a198735bSStefano Zampini     }
789857de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
789957de7509SStefano Zampini     PetscInt    psum;
790057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
790157de7509SStefano Zampini     else psum = 0;
790257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
79037de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
790457de7509SStefano Zampini   }
790557de7509SStefano Zampini   /* determine if we can go multilevel */
790657de7509SStefano Zampini   if (multilevel_requested) {
790757de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
790857de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
790957de7509SStefano Zampini   }
791057de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
791157de7509SStefano Zampini 
7912e4d548c7SStefano Zampini   /* dump subassembling pattern */
7913e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7914e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7915e4d548c7SStefano Zampini   }
7916e4d548c7SStefano Zampini 
79176e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
79181e0482f5SStefano Zampini   nedcfield = -1;
79191e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
79206e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
79216e683305SStefano Zampini     const PetscInt         *idxs;
79226e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
79236e683305SStefano Zampini 
79246e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
79250be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
79266e683305SStefano Zampini     /* allocate space for temporary storage */
7927854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7928854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
79296e683305SStefano Zampini     /* allocate for IS array */
79306e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
79311e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
79321e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
79331e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
79341e0482f5SStefano Zampini       } else {
79351e0482f5SStefano Zampini         nedcfield = 0;
79361e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
79371e0482f5SStefano Zampini         nisdofs = 1;
79381e0482f5SStefano Zampini       }
79391e0482f5SStefano Zampini     }
79406e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
794127b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
794230368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7943854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
79446e683305SStefano Zampini     /* dofs splitting */
79456e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
79466e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
79471e0482f5SStefano Zampini       if (nedcfield != i) {
79486e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
79496e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
79506e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
79516e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
79521e0482f5SStefano Zampini       } else {
79531e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
79541e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
79551e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7956eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
79571e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
79581e0482f5SStefano Zampini       }
79596e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
796030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
79616e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
79626e683305SStefano Zampini     }
79636e683305SStefano Zampini     /* neumann boundaries */
79646e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
79656e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
79666e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
79676e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
79686e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
79696e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
79706e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
797130368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
79726e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
79736e683305SStefano Zampini     }
79746e683305SStefano Zampini     /* free memory */
79756e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
79766e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
79776e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
79786e683305SStefano Zampini   } else {
79796e683305SStefano Zampini     nis = 0;
79806e683305SStefano Zampini     nisdofs = 0;
79816e683305SStefano Zampini     nisneu = 0;
798230368db7SStefano Zampini     nisvert = 0;
79836e683305SStefano Zampini     isarray = NULL;
79846e683305SStefano Zampini   }
79856e683305SStefano Zampini   /* destroy no longer needed map */
79866e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
79876e683305SStefano Zampini 
798857de7509SStefano Zampini   /* subassemble */
798957de7509SStefano Zampini   if (multilevel_allowed) {
79901ae86dd6SStefano Zampini     Vec       vp[1];
79911ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
799257de7509SStefano Zampini     PetscBool reuse,reuser;
79931ae86dd6SStefano Zampini 
799457de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
799557de7509SStefano Zampini     else reuse = PETSC_FALSE;
799657de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
79971ae86dd6SStefano Zampini     vp[0] = NULL;
79981ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
79991ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
80001ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
80011ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
80021ae86dd6SStefano Zampini       nvecs = 1;
80031ae86dd6SStefano Zampini 
80041ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8005a198735bSStefano Zampini         Mat      B,loc_divudotp;
80061ae86dd6SStefano Zampini         Vec      v,p;
80071ae86dd6SStefano Zampini         IS       dummy;
80081ae86dd6SStefano Zampini         PetscInt np;
80091ae86dd6SStefano Zampini 
8010a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8011a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
80121ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
80137dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
80141ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
80151ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
80161ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
80171ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
80181ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
80191ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
80201ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
80211ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
80221ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
80231ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
80241ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
80251ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
802674e2c79eSStefano Zampini       }
80271ae86dd6SStefano Zampini     }
80281ae86dd6SStefano Zampini     if (reuser) {
80291e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
803074e2c79eSStefano Zampini     } else {
80311e0482f5SStefano 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);
80321ae86dd6SStefano Zampini     }
80331ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
80341ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
80351ae86dd6SStefano Zampini       PetscInt    nl;
80361ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
80371ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
80381ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
80391ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
80401ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
80411ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
80421ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
80431ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8044a198735bSStefano Zampini     } else {
8045a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
80461ae86dd6SStefano Zampini     }
80471ae86dd6SStefano Zampini   } else {
80481e0482f5SStefano 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);
80496e683305SStefano Zampini   }
805057de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
805157de7509SStefano Zampini     PetscMPIInt size;
8052f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
805357de7509SStefano Zampini     if (!multilevel_allowed) {
8054*487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
80556e683305SStefano Zampini     } else {
805657de7509SStefano Zampini       Mat A;
8057779c1cceSStefano Zampini 
805857de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
805957de7509SStefano Zampini       if (coarse_mat_is) {
806057de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
806157de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
806257de7509SStefano Zampini         coarse_mat = coarse_mat_is;
806357de7509SStefano Zampini       }
806457de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
806557de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
806657de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
8067779c1cceSStefano Zampini     }
8068779c1cceSStefano Zampini   }
806957de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
807057de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
80716e683305SStefano Zampini 
80726e683305SStefano Zampini   /* create local to global scatters for coarse problem */
807368457ee5SStefano Zampini   if (compute_vecs) {
80746e683305SStefano Zampini     PetscInt lrows;
80756e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
807657de7509SStefano Zampini     if (coarse_mat) {
807757de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
80786e683305SStefano Zampini     } else {
80796e683305SStefano Zampini       lrows = 0;
80806e683305SStefano Zampini     }
80816e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
80826e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
80836e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
80846e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
80856e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
80866e683305SStefano Zampini   }
80876e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8088c8587f34SStefano Zampini 
8089f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8090f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8091f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8092f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
8093f9eb5b7dSStefano Zampini   } else {
8094f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8095f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
8096c8587f34SStefano Zampini   }
8097c8587f34SStefano Zampini 
80986e683305SStefano Zampini   /* print some info if requested */
80996e683305SStefano Zampini   if (pcbddc->dbg_flag) {
81006e683305SStefano Zampini     if (!multilevel_allowed) {
81016e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
81026e683305SStefano Zampini       if (multilevel_requested) {
81036e683305SStefano 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);
81046e683305SStefano Zampini       } else if (pcbddc->max_levels) {
81056e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
81066e683305SStefano Zampini       }
81076e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
81086e683305SStefano Zampini     }
81096e683305SStefano Zampini   }
81106e683305SStefano Zampini 
81111e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
81121e0482f5SStefano Zampini   coarseG = NULL;
81131e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
81141e0482f5SStefano Zampini     MPI_Comm ccomm;
81151e0482f5SStefano Zampini     if (coarse_mat) {
81161e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
81171e0482f5SStefano Zampini     } else {
81181e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
81191e0482f5SStefano Zampini     }
81201e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
81211e0482f5SStefano Zampini   }
81221e0482f5SStefano Zampini 
8123f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
812457de7509SStefano Zampini   if (coarse_mat) {
81257274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
81266a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
81277274672aSStefano Zampini 
81286e683305SStefano Zampini     if (pcbddc->dbg_flag) {
812957de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
81306e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
81316e683305SStefano Zampini     }
8132f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8133312be037SStefano Zampini       char   prefix[256],str_level[16];
8134e604994aSStefano Zampini       size_t len;
81351e0482f5SStefano Zampini 
813657de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8137422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8138c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8139f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
814057de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8141c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
81426e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8143c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
81441e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8145c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8146e604994aSStefano Zampini       /* prefix */
8147e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8148e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8149e604994aSStefano Zampini       if (!pcbddc->current_level) {
8150a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8151a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8152c8587f34SStefano Zampini       } else {
8153e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8154312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8155312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8156a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
815734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
815835529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8159a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8160e604994aSStefano Zampini       }
8161e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
81623e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
81633e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
81643e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
81653e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8166f9eb5b7dSStefano Zampini       /* allow user customization */
8167f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
81683e3c6dadSStefano Zampini     }
81693e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
817051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
81713e3c6dadSStefano Zampini     if (nisdofs) {
81723e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
81733e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
81743e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
81753e3c6dadSStefano Zampini       }
81763e3c6dadSStefano Zampini     }
81773e3c6dadSStefano Zampini     if (nisneu) {
81783e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
81793e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8180312be037SStefano Zampini     }
818130368db7SStefano Zampini     if (nisvert) {
818230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
818330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
818430368db7SStefano Zampini     }
81851e0482f5SStefano Zampini     if (coarseG) {
81861e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
81871e0482f5SStefano Zampini     }
8188f9eb5b7dSStefano Zampini 
8189f9eb5b7dSStefano Zampini     /* get some info after set from options */
8190f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8191b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8192b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8193f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8194f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
8195f9eb5b7dSStefano Zampini     }
8196b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
81977274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
81987274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
8199b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8200b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
8201b76f3995Sstefano_zampini     }
82027274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
82034f3a063dSStefano Zampini     if (isredundant) {
82044f3a063dSStefano Zampini       KSP inner_ksp;
82054f3a063dSStefano Zampini       PC  inner_pc;
82069326c5c6Sstefano_zampini 
82074f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
82084f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
82094f3a063dSStefano Zampini     }
8210f9eb5b7dSStefano Zampini 
821157de7509SStefano Zampini     /* parameters which miss an API */
82127274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
821357de7509SStefano Zampini     if (isbddc) {
8214720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
82157274672aSStefano Zampini 
8216720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
821757de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
821827b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
821927b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8220a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8221a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8222a198735bSStefano Zampini         IS                     row,col;
8223a198735bSStefano Zampini         const PetscInt         *gidxs;
8224a198735bSStefano Zampini         PetscInt               n,st,M,N;
8225a198735bSStefano Zampini 
8226a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8227a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8228a198735bSStefano Zampini         st   = st-n;
8229a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8230a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8231a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8232a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8233a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8234a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8235a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8236a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8237a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8238a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8239a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8240a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8241a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8242a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8243a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8244a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8245a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8246a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8247a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8248a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
82498ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8250a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8251720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8252bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8253720d30f9SStefano Zampini       }
8254d4d8cf7bSStefano Zampini     }
82559881197aSStefano Zampini 
82563301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
82575a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
82583301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
82593301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
82603301b35fSStefano Zampini     }
82613301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
82623301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
82633301b35fSStefano Zampini     }
82643301b35fSStefano Zampini     if (pc->pmat->spd_set) {
82653301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
82663301b35fSStefano Zampini     }
826727b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
826827b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
826927b6a85dSStefano Zampini     }
82706e683305SStefano Zampini     /* set operators */
827104fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
82725f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
82736e683305SStefano Zampini     if (pcbddc->dbg_flag) {
82746e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
82756e683305SStefano Zampini     }
82766e683305SStefano Zampini   }
82771e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
82786e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8279b1ecc7b1SStefano Zampini #if 0
8280b9b85e73SStefano Zampini   {
8281b9b85e73SStefano Zampini     PetscViewer viewer;
8282b9b85e73SStefano Zampini     char filename[256];
8283b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8284b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
82856a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8286b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8287f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8288b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8289b9b85e73SStefano Zampini   }
8290b9b85e73SStefano Zampini #endif
8291f9eb5b7dSStefano Zampini 
829298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
829398a51de6SStefano Zampini     Vec crhs,csol;
829404708bb6SStefano Zampini 
8295f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8296f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8297f347579bSStefano Zampini     if (!csol) {
82982a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8299f9eb5b7dSStefano Zampini     }
8300f347579bSStefano Zampini     if (!crhs) {
83012a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8302f347579bSStefano Zampini     }
8303b0f5fe93SStefano Zampini   }
83041ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8305b0f5fe93SStefano Zampini 
8306b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8307b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8308b0f5fe93SStefano Zampini 
8309b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
83104f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
83114f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
83124f1b2e48SStefano Zampini     }
8313b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8314b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8315b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8316b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8317b0f5fe93SStefano Zampini     if (coarse_mat) {
8318b0f5fe93SStefano Zampini       Vec         nullv;
8319b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8320b0f5fe93SStefano Zampini       PetscInt    nl;
8321b0f5fe93SStefano Zampini 
8322b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8323b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8324b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8325b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8326b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8327b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8328b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8329b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8330b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8331b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8332b0f5fe93SStefano Zampini     }
8333b0f5fe93SStefano Zampini   }
8334b0f5fe93SStefano Zampini 
8335b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8336b0f5fe93SStefano Zampini     PetscBool ispreonly;
8337b0f5fe93SStefano Zampini 
8338b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8339b0f5fe93SStefano Zampini       PetscBool isnull;
8340b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8341bef83e63SStefano Zampini       if (isnull) {
8342b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8343b0f5fe93SStefano Zampini       }
8344bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8345b0f5fe93SStefano Zampini     }
8346b0f5fe93SStefano Zampini     /* setup coarse ksp */
8347b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8348cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8349cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
83506e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8351c8587f34SStefano Zampini       KSP       check_ksp;
83522b510759SStefano Zampini       KSPType   check_ksp_type;
8353c8587f34SStefano Zampini       PC        check_pc;
83546e683305SStefano Zampini       Vec       check_vec,coarse_vec;
83556a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
83562b510759SStefano Zampini       PetscInt  its;
83576e683305SStefano Zampini       PetscBool compute_eigs;
83586e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
83596e683305SStefano Zampini       PetscInt  neigs;
83608e185a42SStefano Zampini       const char *prefix;
8361c8587f34SStefano Zampini 
83622b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
83636e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
8364422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
836523ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8366f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8367e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8368e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8369e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
83702b510759SStefano Zampini       if (ispreonly) {
83712b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
83726e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
83732b510759SStefano Zampini       } else {
8374cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
83756e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8376c8587f34SStefano Zampini       }
8377c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
83786e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
83796e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
83806e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8381a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8382a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8383a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8384a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8385c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8386c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8387c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8388c8587f34SStefano Zampini       /* create random vec */
83892701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8390c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
83916e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8392c8587f34SStefano Zampini       /* solve coarse problem */
83936e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8394cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
83956e683305SStefano Zampini       if (compute_eigs) {
8396854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8397854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
83986e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
83991ae86dd6SStefano Zampini         if (neigs) {
84006e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
84016e683305SStefano Zampini           lambda_min = eigs_r[0];
84026e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
84032701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
84042701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8405cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8406cbcc2c2aSStefano Zampini             }
8407c8587f34SStefano Zampini           }
8408c8587f34SStefano Zampini         }
84091ae86dd6SStefano Zampini       }
8410cbcc2c2aSStefano Zampini 
8411c8587f34SStefano Zampini       /* check coarse problem residual error */
84126e683305SStefano Zampini       if (pcbddc->dbg_flag) {
84136e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
84146e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
84156e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8416c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
84176e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
84186e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8419779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
84206e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
84216e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
84226e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
84236e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8424b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8425b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8426b0f5fe93SStefano Zampini         }
84276e683305SStefano Zampini         if (compute_eigs) {
84286e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8429b03ebc13SStefano Zampini           KSPConvergedReason reason;
8430deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8431c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8432b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
84336e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8434b03ebc13SStefano 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);
84356e683305SStefano Zampini           for (i=0;i<neigs;i++) {
84366e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8437c8587f34SStefano Zampini           }
84386e683305SStefano Zampini         }
84396e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
84406e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
84416e683305SStefano Zampini       }
8442e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
84432701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8444c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
84456e683305SStefano Zampini       if (compute_eigs) {
84466e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
84476e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8448c8587f34SStefano Zampini       }
84496e683305SStefano Zampini     }
84506e683305SStefano Zampini   }
8451bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8452cbcc2c2aSStefano Zampini   /* print additional info */
8453cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
84546e683305SStefano Zampini     /* waits until all processes reaches this point */
84556e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
8456cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
8457cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8458cbcc2c2aSStefano Zampini   }
8459cbcc2c2aSStefano Zampini 
84602b510759SStefano Zampini   /* free memory */
8461fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
8462c8587f34SStefano Zampini   PetscFunctionReturn(0);
8463c8587f34SStefano Zampini }
8464674ae819SStefano Zampini 
8465f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8466f34684f1SStefano Zampini {
8467f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8468f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8469f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8470dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8471dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
847273be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8473dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8474f34684f1SStefano Zampini   PetscErrorCode ierr;
8475f34684f1SStefano Zampini 
8476f34684f1SStefano Zampini   PetscFunctionBegin;
8477f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
84786c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8479dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
84803bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8481dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8482dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
84836583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8484dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8485dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8486dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
84876c4ed002SBarry 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);
8488dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8489dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8490dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8491dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8492dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8493f34684f1SStefano Zampini 
8494f34684f1SStefano Zampini   /* check numbering */
8495f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8496019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8497dc456d91SStefano Zampini     PetscInt    i;
8498b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8499f34684f1SStefano Zampini 
8500f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8501f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8502f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
85031575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8504019a44ceSStefano Zampini     /* counter */
8505019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8506019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8507019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8508019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8509019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8510019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8511f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8512f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8513727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8514f34684f1SStefano Zampini     }
8515f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8516f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8517f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8518e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8519e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8520e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8521e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8522f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8523019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8524f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8525019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
85262c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
852775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8528b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
85292c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
85302c66d082SStefano 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);
8531f34684f1SStefano Zampini       }
8532f34684f1SStefano Zampini     }
8533019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8534b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8535f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8536f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8537f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8538f34684f1SStefano Zampini     }
8539f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8540f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8541e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8542e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8543f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8544f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8545b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8546ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8547ca8b9ea9SStefano Zampini 
8548ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
85493bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8550f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8551f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8552f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8553f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
85544bc2dc4bSStefano 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);
8555f34684f1SStefano Zampini       }
8556f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8557ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8558f34684f1SStefano Zampini     }
8559f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
85601575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8561302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8562f34684f1SStefano Zampini   }
85638bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8564f34684f1SStefano Zampini   /* get back data */
8565f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8566f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8567674ae819SStefano Zampini   PetscFunctionReturn(0);
8568674ae819SStefano Zampini }
8569674ae819SStefano Zampini 
8570a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8571e456f2a8SStefano Zampini {
8572e456f2a8SStefano Zampini   IS             localis_t;
8573a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8574e456f2a8SStefano Zampini   PetscScalar    *vals;
8575e456f2a8SStefano Zampini   PetscErrorCode ierr;
8576e456f2a8SStefano Zampini 
8577e456f2a8SStefano Zampini   PetscFunctionBegin;
8578a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8579e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8580854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8581e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8582e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8583a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8584a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
85851035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
85863151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8587a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
85881035eff8SStefano Zampini   }
8589a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8590e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8591e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8592a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8593a7dc3881SStefano Zampini   /* now compute set in local ordering */
8594a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8595a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8596a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8597a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8598a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8599ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8600e456f2a8SStefano Zampini       lsize++;
8601e456f2a8SStefano Zampini     }
8602e456f2a8SStefano Zampini   }
8603854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8604a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8605ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8606e456f2a8SStefano Zampini       idxs[lsize++] = i;
8607e456f2a8SStefano Zampini     }
8608e456f2a8SStefano Zampini   }
8609a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8610a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8611e456f2a8SStefano Zampini   *localis = localis_t;
8612e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8613e456f2a8SStefano Zampini }
8614906d46d4SStefano Zampini 
861508122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8616b96c3477SStefano Zampini {
8617a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8618b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8619b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8620a64f4aa4SStefano Zampini   Mat                 S_j;
8621b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8622b96c3477SStefano Zampini   PetscBool           free_used_adj;
8623b96c3477SStefano Zampini   PetscErrorCode      ierr;
8624b96c3477SStefano Zampini 
8625b96c3477SStefano Zampini   PetscFunctionBegin;
8626b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8627b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
862808122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8629b96c3477SStefano Zampini     used_xadj = NULL;
8630b96c3477SStefano Zampini     used_adjncy = NULL;
8631b96c3477SStefano Zampini   } else {
863208122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
863308122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
863408122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
863508122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8636b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8637b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8638b96c3477SStefano Zampini     } else {
86392fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8640b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8641b96c3477SStefano Zampini       PetscInt       nvtxs;
8642b96c3477SStefano Zampini 
86432fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
86442fffb893SStefano Zampini       if (flg_row) {
8645b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8646b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8647b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8648b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
86492fffb893SStefano Zampini       } else {
86502fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
86512fffb893SStefano Zampini         used_xadj = NULL;
86522fffb893SStefano Zampini         used_adjncy = NULL;
86532fffb893SStefano Zampini       }
86542fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8655b96c3477SStefano Zampini     }
8656b96c3477SStefano Zampini   }
8657d5574798SStefano Zampini 
8658d5574798SStefano Zampini   /* setup sub_schurs data */
8659a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8660df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8661df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8662a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
866391af6908SStefano 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);
8664a64f4aa4SStefano Zampini   } else {
866572b8c272SStefano Zampini     Mat       change = NULL;
86669d54b7f4SStefano Zampini     Vec       scaling = NULL;
8667111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8668111315fdSstefano_zampini     PetscInt  benign_n;
8669111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8670111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8671111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8672a3df083aSStefano Zampini 
86735feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
86745feab87aSStefano Zampini       PetscInt n_vertices;
86755feab87aSStefano Zampini 
86765feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
86772034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
86785feab87aSStefano Zampini     }
867904708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
868004708bb6SStefano Zampini     if (!isseqaij) {
868104708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
868204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
868304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
868404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
868504708bb6SStefano Zampini       } else {
8686511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
868704708bb6SStefano Zampini       }
868804708bb6SStefano Zampini     }
8689a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8690a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8691ca92afb2SStefano Zampini     } else {
8692a3df083aSStefano Zampini       benign_n = 0;
8693ca92afb2SStefano Zampini     }
8694b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8695b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8696b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
869772b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
869822db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8699b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
870022db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8701b7ab4a40SStefano Zampini     }
8702b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8703b7ab4a40SStefano 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 */
8704b7ab4a40SStefano Zampini     if (need_change) {
870588c03ad3SStefano Zampini       PC_IS   *pcisf;
870688c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
870788c03ad3SStefano Zampini       PC      pcf;
870888c03ad3SStefano Zampini 
8709e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
871088c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
871188c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
871288c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8713b9be95fcSstefano_zampini 
871488c03ad3SStefano Zampini       /* hacks */
871588c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
871672b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
871772b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
871872b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
871972b8c272SStefano Zampini       pcisf->n                     = pcis->n;
872072b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
872188c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
872288c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
872388c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
872488c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
872588c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
872688c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
872772b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
872888c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8729b9be95fcSstefano_zampini 
8730b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
873188c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
873272b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
873372b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
873472b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
873572b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8736b9be95fcSstefano_zampini 
873788c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
873872b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
873988c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
874088c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
874188c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
874288c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
874388c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
874488c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8745b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
874688c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
874788c03ad3SStefano Zampini     }
87489d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8749111315fdSstefano_zampini 
8750111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8751111315fdSstefano_zampini     if (iP) {
8752111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8753111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8754111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8755111315fdSstefano_zampini     }
8756111315fdSstefano_zampini     if (discrete_harmonic) {
8757111315fdSstefano_zampini       Mat A;
8758111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8759111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8760111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8761111315fdSstefano_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);
8762111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8763111315fdSstefano_zampini     } else {
876491af6908SStefano 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);
8765111315fdSstefano_zampini     }
876672b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
876772b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8768ca92afb2SStefano Zampini   }
8769d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8770b96c3477SStefano Zampini 
8771b96c3477SStefano Zampini   /* free adjacency */
8772b96c3477SStefano Zampini   if (free_used_adj) {
8773b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8774b96c3477SStefano Zampini   }
8775b96c3477SStefano Zampini   PetscFunctionReturn(0);
8776b96c3477SStefano Zampini }
8777b96c3477SStefano Zampini 
877808122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8779b96c3477SStefano Zampini {
8780b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8781b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8782b96c3477SStefano Zampini   PCBDDCGraph         graph;
8783b96c3477SStefano Zampini   PetscErrorCode      ierr;
8784b96c3477SStefano Zampini 
8785b96c3477SStefano Zampini   PetscFunctionBegin;
8786b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
878708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
87883301b35fSStefano Zampini     IS       verticesIS,verticescomm;
87893301b35fSStefano Zampini     PetscInt vsize,*idxs;
8790b96c3477SStefano Zampini 
8791b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
87923301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
87933301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
87943301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
87953301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8796c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8797b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8798be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8799441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
88003301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8801b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8802b96c3477SStefano Zampini   } else {
8803b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8804b96c3477SStefano Zampini   }
8805e4d548c7SStefano Zampini   /* print some info */
88065c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8807e4d548c7SStefano Zampini     IS       vertices;
8808e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8809c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8810e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8811e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8812e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8813e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8814e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8815e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8816e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8817e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8818e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8819c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8820e4d548c7SStefano Zampini   }
8821b96c3477SStefano Zampini 
8822b96c3477SStefano Zampini   /* sub_schurs init */
8823b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8824b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8825b334f244SStefano Zampini   }
882688113c35SStefano 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);
8827a64f4aa4SStefano Zampini 
8828b96c3477SStefano Zampini   /* free graph struct */
882908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8830b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8831b96c3477SStefano Zampini   }
8832b96c3477SStefano Zampini   PetscFunctionReturn(0);
8833b96c3477SStefano Zampini }
8834fa34dd3eSStefano Zampini 
8835fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8836fa34dd3eSStefano Zampini {
8837fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8838fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8839fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8840fa34dd3eSStefano Zampini 
8841fa34dd3eSStefano Zampini   PetscFunctionBegin;
8842fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8843fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
88444f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8845fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
88464f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
884775c01103SStefano Zampini     PetscReal      norm;
8848fa34dd3eSStefano Zampini     PetscInt       i;
8849fa34dd3eSStefano Zampini 
8850fa34dd3eSStefano Zampini     /* B0 and B0_B */
8851fa34dd3eSStefano Zampini     if (zerodiag) {
8852fa34dd3eSStefano Zampini       IS       dummy;
8853fa34dd3eSStefano Zampini 
88544f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
88557dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8856fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8857fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8858fa34dd3eSStefano Zampini     }
8859fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8860fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8861fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8862fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8863fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8864fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8865fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8866fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8867fa34dd3eSStefano Zampini     /* S_j */
8868fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8869fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8870fa34dd3eSStefano Zampini 
8871fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8872fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8873fa34dd3eSStefano Zampini     /* continuous in primal space */
8874fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8875fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8876fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8877fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
88784f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
88794f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8880fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8881fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8882fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8883fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8884fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8885fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8886fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8887fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8888fa34dd3eSStefano Zampini 
8889fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8890fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8891fa34dd3eSStefano Zampini     /* local with Schur */
8892fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8893fa34dd3eSStefano Zampini     if (zerodiag) {
8894fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
88954f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8896fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8897fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8898fa34dd3eSStefano Zampini     }
8899fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8900fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8901fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8902fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8903fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8904fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8905fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8906fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8907fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8908fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8909fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8910fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8911fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8912fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8913fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8914fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8915fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8916fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8917fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8918fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8919fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8920fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8921fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8922fa34dd3eSStefano Zampini     if (zerodiag) {
8923fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8924fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
89254f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8926fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8927fa34dd3eSStefano Zampini     }
8928fa34dd3eSStefano Zampini     /* BDDC */
8929fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8930fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8931fa34dd3eSStefano Zampini 
8932fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8933fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8934fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8935fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
89364f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
89374f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8938fa34dd3eSStefano Zampini     }
89394f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8940fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8941fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8942fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8943fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8944fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8945fa34dd3eSStefano Zampini   }
8946fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8947fa34dd3eSStefano Zampini }
89481e0482f5SStefano Zampini 
89491e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
89501e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
89511e0482f5SStefano Zampini {
89521e0482f5SStefano Zampini   Mat            At;
89531e0482f5SStefano Zampini   IS             rows;
89541e0482f5SStefano Zampini   PetscInt       rst,ren;
89551e0482f5SStefano Zampini   PetscErrorCode ierr;
89561e0482f5SStefano Zampini   PetscLayout    rmap;
89571e0482f5SStefano Zampini 
89581e0482f5SStefano Zampini   PetscFunctionBegin;
89591e0482f5SStefano Zampini   rst = ren = 0;
89601e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
89611e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
89621e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
89631e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
89641e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
89651e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
89661e0482f5SStefano Zampini   }
8967e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
89687dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
89691e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
89701e0482f5SStefano Zampini 
89711e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
89721e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
89731e0482f5SStefano Zampini     IS         from,to;
89741e0482f5SStefano Zampini     Vec        gvec;
89751e0482f5SStefano Zampini     PetscInt   lsize;
89761e0482f5SStefano Zampini 
89771e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
89781e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
89791e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
89801e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
89811e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
89821e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
89831e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
89841e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
89851e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
89861e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
89871e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
89881e0482f5SStefano Zampini     b->A = a->A;
89891e0482f5SStefano Zampini     b->B = a->B;
89901e0482f5SStefano Zampini 
89911e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
89921e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
89931e0482f5SStefano Zampini     b->rowindices      = 0;
89941e0482f5SStefano Zampini     b->rowvalues       = 0;
89951e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
89961e0482f5SStefano Zampini 
89971e0482f5SStefano Zampini     (*B)->rmap         = rmap;
89981e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
89991e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
90001e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
90011e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
90021e0482f5SStefano Zampini 
90031e0482f5SStefano Zampini     if (a->colmap) {
90041e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
90051e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
90061e0482f5SStefano Zampini #else
90071e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
90081e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90091e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90101e0482f5SStefano Zampini #endif
90111e0482f5SStefano Zampini     } else b->colmap = 0;
90121e0482f5SStefano Zampini     if (a->garray) {
90131e0482f5SStefano Zampini       PetscInt len;
90141e0482f5SStefano Zampini       len  = a->B->cmap->n;
90151e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
90161e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
90171e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
90181e0482f5SStefano Zampini     } else b->garray = 0;
90191e0482f5SStefano Zampini 
90201e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
90211e0482f5SStefano Zampini     b->lvec = a->lvec;
90221e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
90231e0482f5SStefano Zampini 
90241e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
90251e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
90261e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
90271e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
90281e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
90291e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
90301e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
90311e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
90321e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
90331e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
90341e0482f5SStefano Zampini   }
90351e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
90361e0482f5SStefano Zampini   PetscFunctionReturn(0);
90371e0482f5SStefano Zampini }
9038