xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision cd18cfedae68b4353acd988fda7a8748e202e151)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h>
5c80a6c00SStefano Zampini #include <petscdmplex.h>
6674ae819SStefano Zampini #include <petscblaslapack.h>
7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h>
97620a527SStefano Zampini #include <petscdmda.h>
10674ae819SStefano Zampini 
111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
121e0482f5SStefano Zampini 
13f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
14f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
16a13144ffSStefano Zampini {
17a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
18a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
19a13144ffSStefano Zampini   PetscReal      *sing;
20a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
21a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
22a13144ffSStefano Zampini   PetscErrorCode ierr;
23a13144ffSStefano Zampini 
24a13144ffSStefano Zampini   PetscFunctionBegin;
25a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
26a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
27614dbb09SStefano Zampini #else
28a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
29a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
30a13144ffSStefano Zampini 
31a13144ffSStefano Zampini   /* workspace */
32a13144ffSStefano Zampini   if (!work) {
33a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
34f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
35a13144ffSStefano Zampini   } else {
36a13144ffSStefano Zampini     ulw   = lw;
37a13144ffSStefano Zampini     uwork = work;
38a13144ffSStefano Zampini   }
39a13144ffSStefano Zampini   n = PetscMin(nr,nc);
40a13144ffSStefano Zampini   if (!rwork) {
41a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
42a13144ffSStefano Zampini   } else {
43a13144ffSStefano Zampini     sing = rwork;
44a13144ffSStefano Zampini   }
45a13144ffSStefano Zampini 
46a13144ffSStefano Zampini   /* SVD */
47a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
55a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
56a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
57a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
58a13144ffSStefano Zampini   if (!rwork) {
59a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   if (!work) {
62a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
63a13144ffSStefano Zampini   }
64a13144ffSStefano Zampini   /* create B */
65f498cd09SStefano Zampini   if (!range) {
66a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
67a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
68a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
69f498cd09SStefano Zampini   } else {
70f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
71f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
72f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
73f498cd09SStefano Zampini   }
74a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
75a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
76614dbb09SStefano Zampini #endif
77614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
78a13144ffSStefano Zampini   PetscFunctionBegin;
79a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
80a13144ffSStefano Zampini #endif
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1237dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
156a13144ffSStefano Zampini {
157a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
158a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1590569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
160eee23b56SStefano Zampini   Vec                    tvec;
161a13144ffSStefano Zampini   PetscSF                sfv;
1621e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
163a13144ffSStefano Zampini   MPI_Comm               comm;
164c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
165c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1667d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
167a13144ffSStefano Zampini   PetscScalar            *vals,*work;
168a13144ffSStefano Zampini   PetscReal              *rwork;
169a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1701e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
171a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
172eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
173b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
174a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
175b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
176637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
177b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179b03ebc13SStefano Zampini #endif
180213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
181a13144ffSStefano Zampini   PetscErrorCode         ierr;
182a13144ffSStefano Zampini 
183a13144ffSStefano Zampini   PetscFunctionBegin;
184213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
185213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
186213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
187213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
188213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
189213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
190213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
191213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
192a13144ffSStefano Zampini   print      = PETSC_FALSE;
193213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
194a13144ffSStefano Zampini 
195213b8bfaSStefano Zampini   /* Command line customization */
196213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
201213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
202213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203213b8bfaSStefano Zampini 
204213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2051e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2061e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   if (!singular) {
209a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
210a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
211c2151214SStefano Zampini     for (i=0;i<n;i++) {
212a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
213a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
214a13144ffSStefano Zampini         break;
215a13144ffSStefano Zampini       }
216a13144ffSStefano Zampini     }
217a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
219a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
220213b8bfaSStefano Zampini   }
221a13144ffSStefano Zampini 
222213b8bfaSStefano Zampini   /* Get Nedelec field */
223213b8bfaSStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
224c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= pcbddc->n_ISForDofsLocal) SETERRQ2(comm,PETSC_ERR_USER,"Invalid field for Nedelec %d: number of fields is %d",field,pcbddc->n_ISForDofsLocal);
225213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
226c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
227c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
228c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
229213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
230213b8bfaSStefano Zampini     ne            = n;
231213b8bfaSStefano Zampini     nedfieldlocal = NULL;
232213b8bfaSStefano Zampini     global        = PETSC_TRUE;
233213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
234213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
235213b8bfaSStefano Zampini 
236213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
237213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
238213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
239213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
240213b8bfaSStefano Zampini       PetscInt nc;
241213b8bfaSStefano Zampini 
242213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
243213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
244213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
245213b8bfaSStefano Zampini     }
246213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
248213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
249213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
250213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
251213b8bfaSStefano Zampini   } else {
252213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
253213b8bfaSStefano Zampini   }
254213b8bfaSStefano Zampini 
255213b8bfaSStefano Zampini   /* Sanity checks */
256213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
257213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
258213b8bfaSStefano Zampini   if (order && ne%order) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %d it's not a multiple of the order %d",ne,order);
259213b8bfaSStefano Zampini 
260213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2611e0482f5SStefano Zampini   if (setprimal) {
262eee23b56SStefano Zampini     IS       enedfieldlocal;
263eee23b56SStefano Zampini     PetscInt *eidxs;
264eee23b56SStefano Zampini 
265eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
266eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
267213b8bfaSStefano Zampini     if (nedfieldlocal) {
268213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
269eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
270eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
271eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
272eee23b56SStefano Zampini         }
273eee23b56SStefano Zampini       }
274eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
275213b8bfaSStefano Zampini     } else {
276213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
277213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
278213b8bfaSStefano Zampini           eidxs[cum++] = i;
279213b8bfaSStefano Zampini         }
280213b8bfaSStefano Zampini       }
281213b8bfaSStefano Zampini     }
282213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
285eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
287eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2881e0482f5SStefano Zampini     PetscFunctionReturn(0);
2891e0482f5SStefano Zampini   }
290a13144ffSStefano Zampini 
291213b8bfaSStefano Zampini   /* Compute some l2g maps */
292213b8bfaSStefano Zampini   if (nedfieldlocal) {
293c2151214SStefano Zampini     IS is;
294c2151214SStefano Zampini 
295c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
296c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2981e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2991e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
3001e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
3011e0482f5SStefano Zampini     if (global) {
3021e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3031e0482f5SStefano Zampini       el2g = al2g;
3041e0482f5SStefano Zampini     } else {
3051e0482f5SStefano Zampini       IS gis;
3061e0482f5SStefano Zampini 
3071e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3081e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3091e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3101e0482f5SStefano Zampini     }
311c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
312c2151214SStefano Zampini   } else {
3131e0482f5SStefano Zampini     /* restore default */
3141e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3151e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3161e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3171e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3181e0482f5SStefano Zampini     el2g = al2g;
319c2151214SStefano Zampini     fl2g = NULL;
320c2151214SStefano Zampini   }
321a13144ffSStefano Zampini 
322213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
323c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
324c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
325c2151214SStefano Zampini   if (nedfieldlocal) {
326c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
328c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
329c2151214SStefano Zampini   } else {
330c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
331c2151214SStefano Zampini   }
332c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
334213b8bfaSStefano Zampini 
335213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
336213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
337213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     if (global) {
3391e0482f5SStefano Zampini       PetscInt rst;
3401e0482f5SStefano Zampini 
341c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
342c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
343c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
344c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
345c2151214SStefano Zampini         }
346c2151214SStefano Zampini       }
347a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
348c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3491e0482f5SStefano Zampini     } else {
3501e0482f5SStefano Zampini       PetscInt *tbz;
3511e0482f5SStefano Zampini 
3521e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3561e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3571e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3581e0482f5SStefano Zampini           tbz[cum++] = i;
3591e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3621e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3631e0482f5SStefano Zampini     }
364213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
365213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
366213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
367213b8bfaSStefano Zampini   }
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3727dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
378a13144ffSStefano Zampini 
379213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
380c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
387a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
388213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
389213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
390a13144ffSStefano Zampini 
3911e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
392213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
393a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
394213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
395a13144ffSStefano Zampini 
396213b8bfaSStefano Zampini   if (print) {
397213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
398213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
399213b8bfaSStefano Zampini   }
400213b8bfaSStefano Zampini 
401213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4020569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4030569b399SStefano Zampini 
404a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4054e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4064e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4107d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
411c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
412a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
413a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
414a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
415c2151214SStefano Zampini     IS is;
416c2151214SStefano Zampini 
417c2151214SStefano Zampini     if (fl2g) {
418c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
419c2151214SStefano Zampini     } else {
420c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
421c2151214SStefano Zampini     }
422c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
423c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
424a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
425a13144ffSStefano Zampini       if (idxs[i] >= 0) {
426a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4277d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
428a13144ffSStefano Zampini       }
429a13144ffSStefano Zampini     }
430c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
431c2151214SStefano Zampini     if (fl2g) {
432c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
433c2151214SStefano Zampini     }
434a13144ffSStefano Zampini   }
435a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
436c2151214SStefano Zampini     IS is;
437c2151214SStefano Zampini 
438c2151214SStefano Zampini     if (fl2g) {
439c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
440c2151214SStefano Zampini     } else {
441c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
442c2151214SStefano Zampini     }
443c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
444c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
445a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
446a13144ffSStefano Zampini       if (idxs[i] >= 0) {
447a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
448a13144ffSStefano Zampini       }
449a13144ffSStefano Zampini     }
450c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
451c2151214SStefano Zampini     if (fl2g) {
452c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
453a13144ffSStefano Zampini     }
454c2151214SStefano Zampini   }
455c2151214SStefano Zampini 
456213b8bfaSStefano Zampini   /* Count neighs per dof */
457637e8532SStefano Zampini   ierr = PetscCalloc1(ne,&ecount);CHKERRQ(ierr);
458637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&eneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
460637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
461637e8532SStefano Zampini     cum += n_shared[i];
462637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
463637e8532SStefano Zampini       ecount[shared[i][j]]++;
464637e8532SStefano Zampini     }
465637e8532SStefano Zampini   }
466637e8532SStefano Zampini   if (ne) {
467637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&eneighs[0]);CHKERRQ(ierr);
468637e8532SStefano Zampini   }
469637e8532SStefano Zampini   for (i=1;i<ne;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
470637e8532SStefano Zampini   ierr = PetscMemzero(ecount,ne*sizeof(PetscInt));CHKERRQ(ierr);
471637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
472637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
473637e8532SStefano Zampini       PetscInt k = shared[i][j];
474637e8532SStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
475637e8532SStefano Zampini       ecount[k]++;
476637e8532SStefano Zampini     }
477637e8532SStefano Zampini   }
478637e8532SStefano Zampini   for (i=0;i<ne;i++) {
479637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr);
480637e8532SStefano Zampini   }
481637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
482637e8532SStefano Zampini   ierr = PetscCalloc1(nv,&vcount);CHKERRQ(ierr);
483637e8532SStefano Zampini   ierr = PetscMalloc1(nv,&vneighs);CHKERRQ(ierr);
484637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
485637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
486637e8532SStefano Zampini     cum += n_shared[i];
487637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
488637e8532SStefano Zampini       vcount[shared[i][j]]++;
489637e8532SStefano Zampini     }
490637e8532SStefano Zampini   }
491637e8532SStefano Zampini   if (nv) {
492637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&vneighs[0]);CHKERRQ(ierr);
493637e8532SStefano Zampini   }
494637e8532SStefano Zampini   for (i=1;i<nv;i++) vneighs[i] = vneighs[i-1] + vcount[i-1];
495637e8532SStefano Zampini   ierr = PetscMemzero(vcount,nv*sizeof(PetscInt));CHKERRQ(ierr);
496637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
497637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
498637e8532SStefano Zampini       PetscInt k = shared[i][j];
499637e8532SStefano Zampini       vneighs[k][vcount[k]] = neigh[i];
500637e8532SStefano Zampini       vcount[k]++;
501637e8532SStefano Zampini     }
502637e8532SStefano Zampini   }
503637e8532SStefano Zampini   for (i=0;i<nv;i++) {
504637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&vcount[i],vneighs[i]);CHKERRQ(ierr);
505637e8532SStefano Zampini   }
506637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
507637e8532SStefano Zampini 
5087d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
5097d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
51062b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
5127d871cd7SStefano Zampini     if ((ecount[i] > 1 && !PetscBTLookup(btbd,i)) || (ecount[i] == 1 && PetscBTLookup(btb,i))) {
51362b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
51462b0c6f7SStefano Zampini     }
51562b0c6f7SStefano Zampini   }
516637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
51762b0c6f7SStefano Zampini   if (!conforming) {
51862b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
51962b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52062b0c6f7SStefano Zampini   }
5214e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
52362b0c6f7SStefano Zampini   cum  = 0;
524a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
525dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
52662b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
527a13144ffSStefano Zampini       marks[cum++] = i;
528dec27d64SStefano Zampini       continue;
529dec27d64SStefano Zampini     }
530dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
53162b0c6f7SStefano Zampini     if (!conforming) {
53262b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
533a13144ffSStefano Zampini         marks[cum++] = i;
534a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
535a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
536a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
537a13144ffSStefano Zampini         }
53862b0c6f7SStefano Zampini       } else {
53962b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
54062b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
54162b0c6f7SStefano Zampini            - at most 2 endpoints
54262b0c6f7SStefano Zampini            - order-1 interior nodal dofs
54362b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
54462b0c6f7SStefano Zampini         */
54562b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
54662b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
54762b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
54862b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
54962b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
55062b0c6f7SStefano Zampini           if (nconn > order) ends++;
55162b0c6f7SStefano Zampini           else if (nconn == order) ints++;
55262b0c6f7SStefano Zampini           else undef++;
55362b0c6f7SStefano Zampini         }
55462b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
55562b0c6f7SStefano Zampini           marks[cum++] = i;
55662b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
55762b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
55862b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
55962b0c6f7SStefano Zampini           }
56062b0c6f7SStefano Zampini         }
56162b0c6f7SStefano Zampini       }
562a13144ffSStefano Zampini     }
563dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
564dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
565dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
566dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
567a13144ffSStefano Zampini     }
568dec27d64SStefano Zampini   }
56962b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
570dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5714e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
57262b0c6f7SStefano Zampini   if (!conforming) {
57362b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
57462b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
57562b0c6f7SStefano Zampini   }
5764e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
577637e8532SStefano Zampini 
578b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5794e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
580a13144ffSStefano Zampini   if (print) {
5814e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5824e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5834e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
584a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
585a13144ffSStefano Zampini   }
586a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
587dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
588a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
589637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5907d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
591b03ebc13SStefano Zampini     if (!order) { /* variable order */
592dec27d64SStefano Zampini       PetscReal vorder = 0.;
593dec27d64SStefano Zampini 
594dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
595dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
596dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
597dec27d64SStefano Zampini       ord  = 1;
598dec27d64SStefano Zampini     }
599a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
600dec27d64SStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",test,i,ord);
601a13144ffSStefano Zampini #endif
602637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
6037d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
6047d871cd7SStefano Zampini         bdir = PETSC_TRUE;
6057d871cd7SStefano Zampini         break;
6067d871cd7SStefano Zampini       }
607637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
608637e8532SStefano Zampini         sneighs = PETSC_FALSE;
609637e8532SStefano Zampini       } else {
610637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
611637e8532SStefano Zampini         for (k=0;k<vc;k++) {
612637e8532SStefano Zampini           if (vn[k] != en[k]) {
613637e8532SStefano Zampini             sneighs = PETSC_FALSE;
614637e8532SStefano Zampini             break;
615637e8532SStefano Zampini           }
616637e8532SStefano Zampini         }
617637e8532SStefano Zampini       }
618637e8532SStefano Zampini     }
6197d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
6207d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
621a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
622dec27d64SStefano Zampini     } else if (test == ord) {
623b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
624a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
625a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
626a13144ffSStefano Zampini       } else {
627a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
628a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
629a13144ffSStefano Zampini       }
630a13144ffSStefano Zampini     }
631a13144ffSStefano Zampini   }
632637e8532SStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
633637e8532SStefano Zampini   ierr = PetscFree(vcount);CHKERRQ(ierr);
634637e8532SStefano Zampini   if (ne) {
635637e8532SStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
636637e8532SStefano Zampini   }
637637e8532SStefano Zampini   if (nv) {
638637e8532SStefano Zampini     ierr = PetscFree(vneighs[0]);CHKERRQ(ierr);
639637e8532SStefano Zampini   }
640637e8532SStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
641637e8532SStefano Zampini   ierr = PetscFree(vneighs);CHKERRQ(ierr);
6427d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
643b03ebc13SStefano Zampini 
644b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
645b03ebc13SStefano Zampini   if (order != 1) {
646b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
647b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
648b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
649b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
650b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
651b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
652b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
653b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
654b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
655b03ebc13SStefano Zampini             PetscInt v = jjt[k];
656b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
657b03ebc13SStefano Zampini               found = PETSC_TRUE;
658b03ebc13SStefano Zampini               break;
659b03ebc13SStefano Zampini             }
660b03ebc13SStefano Zampini           }
661b03ebc13SStefano Zampini         }
662b03ebc13SStefano Zampini         if (!found) {
663b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
664b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
665b03ebc13SStefano Zampini         } else {
666b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
667b03ebc13SStefano Zampini         }
668b03ebc13SStefano Zampini       }
669b03ebc13SStefano Zampini     }
670b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
671b03ebc13SStefano Zampini   }
672dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
673a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
674b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
675a13144ffSStefano Zampini 
676a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6770569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
678a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6794e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
680a13144ffSStefano Zampini 
6814e64d54eSstefano_zampini   /* Mark interior nodal dofs */
682a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6834e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
684a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
685a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6864e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
687a13144ffSStefano Zampini     }
688a13144ffSStefano Zampini   }
689a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
690a13144ffSStefano Zampini 
691a13144ffSStefano Zampini   /* communicate corners and splitpoints */
692a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
693a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
694a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
695a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
696a13144ffSStefano Zampini 
697a13144ffSStefano Zampini   if (print) {
698a13144ffSStefano Zampini     IS tbz;
699a13144ffSStefano Zampini 
700a13144ffSStefano Zampini     cum = 0;
701a13144ffSStefano Zampini     for (i=0;i<nv;i++)
702a13144ffSStefano Zampini       if (sfvleaves[i])
703a13144ffSStefano Zampini         vmarks[cum++] = i;
704a13144ffSStefano Zampini 
705a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
706a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
707a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
708a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
709a13144ffSStefano Zampini   }
710a13144ffSStefano Zampini 
711a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
712a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
713a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
715a13144ffSStefano Zampini 
7164e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
7174e64d54eSstefano_zampini      and interior nodal dofs */
718a13144ffSStefano Zampini   cum = 0;
719a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
720a13144ffSStefano Zampini     if (sfvleaves[i]) {
721a13144ffSStefano Zampini       vmarks[cum++] = i;
722a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
723a13144ffSStefano Zampini     }
7244e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
725a13144ffSStefano Zampini   }
7264e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
727a13144ffSStefano Zampini   if (print) {
728a13144ffSStefano Zampini     IS tbz;
729a13144ffSStefano Zampini 
730a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
7314e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
732a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
733a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
734a13144ffSStefano Zampini   }
735a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
736a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
737a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
738a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
739a13144ffSStefano Zampini 
740a13144ffSStefano Zampini   /* Recompute G */
741a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
742a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
743a13144ffSStefano Zampini   if (print) {
744a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
745a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
746a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
747a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
748a13144ffSStefano Zampini   }
749a13144ffSStefano Zampini 
750a13144ffSStefano Zampini   /* Get primal dofs (if any) */
751a13144ffSStefano Zampini   cum = 0;
752a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
753a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
754a13144ffSStefano Zampini   }
755c2151214SStefano Zampini   if (fl2g) {
756c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
757c2151214SStefano Zampini   }
758a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
759a13144ffSStefano Zampini   if (print) {
760a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
761a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
762a13144ffSStefano Zampini   }
763a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
764c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
765a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
766a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
767a13144ffSStefano Zampini 
768a13144ffSStefano Zampini   /* Compute edge connectivity */
769a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
770a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
771a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
772c2151214SStefano Zampini   if (fl2g) {
773c2151214SStefano Zampini     PetscBT   btf;
774c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
775c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
776c2151214SStefano Zampini 
777c2151214SStefano Zampini     /* create CSR for all local dofs */
778c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
779c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
780c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %d. Should be %d\n",pcbddc->mat_graph->nvtxs_csr,n);
781c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
782c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
783c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
784c2151214SStefano Zampini       rest = PETSC_TRUE;
785c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
786c2151214SStefano Zampini     } else {
787c2151214SStefano Zampini       free   = PETSC_TRUE;
788c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
789c2151214SStefano Zampini       iiu[0] = 0;
790c2151214SStefano Zampini       for (i=0;i<n;i++) {
791c2151214SStefano Zampini         iiu[i+1] = i+1;
792c2151214SStefano Zampini         jju[i]   = -1;
793d904f53bSStefano Zampini       }
794c2151214SStefano Zampini     }
795c2151214SStefano Zampini 
796c2151214SStefano Zampini     /* import sizes of CSR */
797c2151214SStefano Zampini     iia[0] = 0;
798c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
799c2151214SStefano Zampini 
800c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
801c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
802c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
803c2151214SStefano Zampini     for (i=0;i<ne;i++) {
804c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
805c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
806c2151214SStefano Zampini     }
807c2151214SStefano Zampini 
808c2151214SStefano Zampini     /* iia in CSR */
809c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
810c2151214SStefano Zampini 
811c2151214SStefano Zampini     /* jja in CSR */
812c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
813c2151214SStefano Zampini     for (i=0;i<n;i++)
814c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
815c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
816c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
817c2151214SStefano Zampini 
818c2151214SStefano Zampini     /* map edge dofs connectivity */
8191e0482f5SStefano Zampini     if (jj) {
820c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
821c2151214SStefano Zampini       for (i=0;i<ne;i++) {
822c2151214SStefano Zampini         PetscInt e = idxs[i];
823c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
824c2151214SStefano Zampini       }
8251e0482f5SStefano Zampini     }
826c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
827c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
828c2151214SStefano Zampini     if (rest) {
829c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
830c2151214SStefano Zampini     }
831c2151214SStefano Zampini     if (free) {
832c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
833c2151214SStefano Zampini     }
834c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
835c2151214SStefano Zampini   } else {
836c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
837c2151214SStefano Zampini   }
838c2151214SStefano Zampini 
839a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
840a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
841213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
842a13144ffSStefano Zampini 
843a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
844c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
845a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
846a13144ffSStefano Zampini 
847c2151214SStefano Zampini   if (fl2g) {
848c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
849c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
850c2151214SStefano Zampini     for (i=0;i<nee;i++) {
851c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
852c2151214SStefano Zampini     }
853c2151214SStefano Zampini   } else {
854c2151214SStefano Zampini     eedges  = alleedges;
855c2151214SStefano Zampini     primals = allprimals;
856c2151214SStefano Zampini   }
857c2151214SStefano Zampini 
858a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
859a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
860c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
861c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
862c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
863c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
864c2151214SStefano Zampini   if (print) {
865c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
866c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
867c2151214SStefano Zampini   }
868c2151214SStefano Zampini 
869c2151214SStefano Zampini   maxsize = 0;
870a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
871a13144ffSStefano Zampini     PetscInt size,mark = i+1;
872a13144ffSStefano Zampini 
873a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
874a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
876a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
878a13144ffSStefano Zampini   }
879a13144ffSStefano Zampini 
880a13144ffSStefano Zampini   /* Find coarse edge endpoints */
881a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
882a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
883a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
884a13144ffSStefano Zampini     PetscInt mark = i+1,size;
885a13144ffSStefano Zampini 
886a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8871e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8881e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
889a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
890a13144ffSStefano Zampini     if (print) {
891a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
892a13144ffSStefano Zampini       ISView(eedges[i],NULL);
893a13144ffSStefano Zampini     }
894a13144ffSStefano Zampini     for (j=0;j<size;j++) {
895a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
896a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
897a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
898a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
899a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
900a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
901a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
902a13144ffSStefano Zampini           PetscInt  k2;
903a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
904a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
905c2151214SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %d: mark %d (ref mark %d), boundary %d\n",jjt[k2],marks[jjt[k2]],mark,!!PetscBTLookup(btb,jjt[k2]));
906c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
907c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
908c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
909a13144ffSStefano Zampini               corner = PETSC_TRUE;
910a13144ffSStefano Zampini               break;
911a13144ffSStefano Zampini             }
912a13144ffSStefano Zampini           }
913a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
914a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
915a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
916a13144ffSStefano Zampini           } else {
917a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
918a13144ffSStefano Zampini           }
919a13144ffSStefano Zampini         }
920a13144ffSStefano Zampini       }
921a13144ffSStefano Zampini     }
922a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
923a13144ffSStefano Zampini   }
924a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
925a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
926c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
927a13144ffSStefano Zampini 
928a13144ffSStefano Zampini   /* Reset marked primal dofs */
929a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
930a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
931a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
932a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
933a13144ffSStefano Zampini 
9340569b399SStefano Zampini   /* Now use the initial lG */
9350569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
9360569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
9370569b399SStefano Zampini   lG   = lGinit;
9380569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
9390569b399SStefano Zampini 
940a13144ffSStefano Zampini   /* Compute extended cols indices */
941b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
942b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
943a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
945a13144ffSStefano Zampini   i   *= maxsize;
946b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
947a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
948a13144ffSStefano Zampini   eerr = PETSC_FALSE;
949a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
950b03ebc13SStefano Zampini     PetscInt size,found = 0;
951a13144ffSStefano Zampini 
952a13144ffSStefano Zampini     cum  = 0;
953a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9541e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9551e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
956a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
957b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
958a13144ffSStefano Zampini     for (j=0;j<size;j++) {
959a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
960b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
961b03ebc13SStefano Zampini         PetscInt vv = jj[k];
962b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
963b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
964b03ebc13SStefano Zampini       }
965a13144ffSStefano Zampini     }
966a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
967a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
968a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
969a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
970a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
971a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
972a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
973b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
974b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
975a13144ffSStefano Zampini       if (print) {
976a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
977a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
978a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
979a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
980a13144ffSStefano Zampini       }
981a13144ffSStefano Zampini       eerr = PETSC_TRUE;
982a13144ffSStefano Zampini     }
983a13144ffSStefano Zampini   }
9844e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
985a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
986a13144ffSStefano Zampini   if (done) {
987a13144ffSStefano Zampini     PetscInt *newprimals;
988a13144ffSStefano Zampini 
989a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
990a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
991a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
992a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
993a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9940569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
995b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
996a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
997b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
998b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
999a13144ffSStefano Zampini         PetscInt size,mark = i+1;
1000a13144ffSStefano Zampini 
1001a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1002a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1003c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
1004a13144ffSStefano Zampini         for (j=0;j<size;j++) {
1005a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
1006b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
1007a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1008a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
1009a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
1010a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
1011b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
1012b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
1013a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
1014a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
1015a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
1016a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
1017a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
1018b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
1019a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
1020a13144ffSStefano Zampini                   /* finally set the new corners */
1021a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
1022b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
1023a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
1024a13144ffSStefano Zampini                   }
1025a13144ffSStefano Zampini                 }
1026a13144ffSStefano Zampini               }
1027b03ebc13SStefano Zampini             } else {
1028b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
1029a13144ffSStefano Zampini             }
1030a13144ffSStefano Zampini           }
1031a13144ffSStefano Zampini         }
1032b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
1033b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
1034b03ebc13SStefano Zampini 
1035b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
1036b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
1037b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1038b03ebc13SStefano Zampini             PetscInt k2;
1039b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
1040b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
1041b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
1042b03ebc13SStefano Zampini           }
1043b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
1044b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
1045b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
1046b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
1047b03ebc13SStefano Zampini             }
1048b03ebc13SStefano Zampini           }
1049b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
1050b03ebc13SStefano Zampini         }
1051a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1052a13144ffSStefano Zampini       }
1053a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1054a13144ffSStefano Zampini     }
1055b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10560569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1057a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1058c2151214SStefano Zampini     if (fl2g) {
1059c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1060c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1061c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1062c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1063c2151214SStefano Zampini       }
1064c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1065c2151214SStefano Zampini     }
1066c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1067a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1068a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1069a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1070a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1071a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1072213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1073c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1074c2151214SStefano Zampini     if (fl2g) {
1075c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1076c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1077c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1078c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1079c2151214SStefano Zampini       }
1080c2151214SStefano Zampini     } else {
1081c2151214SStefano Zampini       eedges  = alleedges;
1082c2151214SStefano Zampini       primals = allprimals;
1083c2151214SStefano Zampini     }
1084b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1085a13144ffSStefano Zampini 
1086a13144ffSStefano Zampini     /* Mark again */
1087a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1088a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1089a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1090a13144ffSStefano Zampini 
1091a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1092a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1093a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1094a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095a13144ffSStefano Zampini     }
1096a13144ffSStefano Zampini     if (print) {
1097a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1098a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1099a13144ffSStefano Zampini     }
1100a13144ffSStefano Zampini 
1101a13144ffSStefano Zampini     /* Recompute extended cols */
1102a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1103a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1104a13144ffSStefano Zampini       PetscInt size;
1105a13144ffSStefano Zampini 
1106a13144ffSStefano Zampini       cum  = 0;
1107a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11081e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
11091e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1110a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1111a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1112a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
11131e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1114a13144ffSStefano Zampini       }
1115a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1116a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1117a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1118a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1119a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1120a13144ffSStefano Zampini       if (cum != size -1) {
1121a13144ffSStefano Zampini         if (print) {
1122a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1123a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1124a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1125a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1126a13144ffSStefano Zampini         }
1127a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1128a13144ffSStefano Zampini       }
1129a13144ffSStefano Zampini     }
1130a13144ffSStefano Zampini   }
1131a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1132a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1133b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
11347d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1135a13144ffSStefano Zampini   /* an error should not occur at this point */
1136a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1137a13144ffSStefano Zampini 
11384e64d54eSstefano_zampini   /* Check the number of endpoints */
11390569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1140b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1141b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
11424e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1143b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
11444e64d54eSstefano_zampini 
1145b03ebc13SStefano Zampini     /* init with defaults */
1146b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
11474e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11481e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
11491e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
11504e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1151b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11524e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11534e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11544e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11554e64d54eSstefano_zampini         PetscInt vv = jj[k];
11564e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1157b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1158b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11594e64d54eSstefano_zampini         }
11604e64d54eSstefano_zampini       }
11614e64d54eSstefano_zampini     }
1162b03ebc13SStefano Zampini     if (found != 2) {
1163b03ebc13SStefano Zampini       PetscInt e;
1164b03ebc13SStefano Zampini       if (fl2g) {
1165b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1166b03ebc13SStefano Zampini       } else {
1167b03ebc13SStefano Zampini         e = idxs[0];
1168b03ebc13SStefano Zampini       }
1169b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1170b03ebc13SStefano Zampini     }
1171eee23b56SStefano Zampini 
1172eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1173b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1174b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1175b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1176b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1177b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1178b03ebc13SStefano Zampini     }
1179eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11804e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1181b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %d: ce %d, corners (%d,%d)\n",i,cedges[i],corners[2*i],corners[2*i+1]);
11824e64d54eSstefano_zampini   }
11830569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11844e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11854e64d54eSstefano_zampini 
1186a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1187a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1188a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1189a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1190a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1191a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1192a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1193a13144ffSStefano Zampini 
1194a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1195a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1196a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1197a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1198a13144ffSStefano Zampini       if (emax < emarks[j]) {
1199a13144ffSStefano Zampini         emax = emarks[j];
1200a13144ffSStefano Zampini         eemax = j;
1201a13144ffSStefano Zampini       }
1202a13144ffSStefano Zampini     }
1203a13144ffSStefano Zampini     /* not relevant for edges */
1204a13144ffSStefano Zampini     if (!eemax) continue;
1205a13144ffSStefano Zampini 
1206a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1207a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1208c2151214SStefano Zampini         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %d and %d) connected through the %d nodal dof at edge dof %d\n",marks[jj[j]]-1,eemax,i,jj[j]);
1209a13144ffSStefano Zampini       }
1210a13144ffSStefano Zampini     }
1211a13144ffSStefano Zampini   }
1212a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1214a13144ffSStefano Zampini #endif
1215a13144ffSStefano Zampini 
1216a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1217a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   extmem *= maxsize;
1220a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1222a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1223a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1224a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1225213b8bfaSStefano Zampini 
1226a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1227a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1228a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1229a13144ffSStefano Zampini         mark = marks[jj[j]];
1230a13144ffSStefano Zampini 
1231a13144ffSStefano Zampini     /* not relevant */
1232a13144ffSStefano Zampini     if (!mark) continue;
1233a13144ffSStefano Zampini 
1234a13144ffSStefano Zampini     /* import extended row */
1235a13144ffSStefano Zampini     mark--;
1236a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1237a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1238a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1239a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1240a13144ffSStefano Zampini     extrowcum[mark] += size;
1241a13144ffSStefano Zampini   }
1242a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1243213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1244213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1245213b8bfaSStefano Zampini 
1246213b8bfaSStefano Zampini   /* Compress extrows */
1247a13144ffSStefano Zampini   cum  = 0;
1248a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1249a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1250a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1251a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1252a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1253a13144ffSStefano Zampini   }
1254a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1255a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1256a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1257a13144ffSStefano Zampini 
1258a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1259a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1260a13144ffSStefano Zampini 
1261a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1262a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1263c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1264c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1265a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1266a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1267a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12681e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1269a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1270a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1271213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1272a13144ffSStefano Zampini 
1273a13144ffSStefano Zampini   /* Defaults to identity */
1274c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1275a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1276a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1277a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1278a13144ffSStefano Zampini 
12791e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12801e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12811e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12821e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12831e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12841e0482f5SStefano Zampini     IS                     wis,gwis;
12851e0482f5SStefano Zampini     PetscInt               cnv,cne;
12861e0482f5SStefano Zampini 
12871e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12881e0482f5SStefano Zampini     if (fl2g) {
12891e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12901e0482f5SStefano Zampini     } else {
12911e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12921e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12931e0482f5SStefano Zampini     }
12941e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12951e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12961e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12971e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12981e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12991e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
13021e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
13031e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13041e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
13051e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
13061e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13071e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13081e0482f5SStefano Zampini 
13091e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
13101e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
13111e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
13121e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
13141e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
13151e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
13161e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
13171e0482f5SStefano Zampini   }
1318213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
13191e0482f5SStefano Zampini 
13201e0482f5SStefano Zampini #if defined(PRINT_GDET)
13211e0482f5SStefano Zampini   inc = 0;
13221e0482f5SStefano Zampini   lev = pcbddc->current_level;
13231e0482f5SStefano Zampini #endif
1324213b8bfaSStefano Zampini 
1325213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1326a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1327a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
13281e0482f5SStefano Zampini     IS          cornersis = NULL;
13291e0482f5SStefano Zampini     PetscScalar cvals[2];
1330a13144ffSStefano Zampini 
13311e0482f5SStefano Zampini     if (pcbddc->nedcG) {
13321e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
13331e0482f5SStefano Zampini     }
13341e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1335a13144ffSStefano Zampini     if (Gins && GKins) {
1336a13144ffSStefano Zampini       PetscScalar    *data;
1337a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1338a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1339a13144ffSStefano Zampini 
1340a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1341a13144ffSStefano Zampini       /* H1 */
1342a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1343a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1344a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1345a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1346a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1347a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1348a13144ffSStefano Zampini       /* complement */
1349a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
13501e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1351213b8bfaSStefano Zampini       if (ncc + nch != nrc) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %d and Gins %d does not match %d for coarse edge %d",ncc,nch,nrc,i);
1352213b8bfaSStefano Zampini       if (ncc != 1 && pcbddc->nedcG) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the coarse discrete gradient for coarse edge %d with ncc %d",i,ncc);
1353a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1354a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1355a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13561e0482f5SStefano Zampini 
13571e0482f5SStefano Zampini       /* coarse discrete gradient */
13581e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13591e0482f5SStefano Zampini         PetscInt cols[2];
13601e0482f5SStefano Zampini 
13611e0482f5SStefano Zampini         cols[0] = 2*i;
13621e0482f5SStefano Zampini         cols[1] = 2*i+1;
13631e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13641e0482f5SStefano Zampini       }
1365a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1366a13144ffSStefano Zampini     }
1367a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1368a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13691e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1370a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1371a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1372a13144ffSStefano Zampini   }
1373213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1374a13144ffSStefano Zampini 
1375a13144ffSStefano Zampini   /* Start assembling */
1376a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13771e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13781e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13791e0482f5SStefano Zampini   }
1380a13144ffSStefano Zampini 
1381a13144ffSStefano Zampini   /* Free */
1382c2151214SStefano Zampini   if (fl2g) {
1383c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1384c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1385c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1386c2151214SStefano Zampini     }
1387c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1388c2151214SStefano Zampini   }
1389eee23b56SStefano Zampini 
1390eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1391eee23b56SStefano Zampini   {
1392eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1393eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1394eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1395eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1396eee23b56SStefano Zampini 
1397eee23b56SStefano Zampini     /* find first primal edge */
1398eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1399eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1400eee23b56SStefano Zampini     } else {
1401eee23b56SStefano Zampini       if (fl2g) {
1402eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1403eee23b56SStefano Zampini       }
1404eee23b56SStefano Zampini       idxs = cedges;
1405eee23b56SStefano Zampini     }
1406eee23b56SStefano Zampini     cum = 0;
1407eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1408eee23b56SStefano Zampini 
1409eee23b56SStefano Zampini     /* adapt connected components */
1410eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1411eee23b56SStefano Zampini     graph->cptr[0] = 0;
1412eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1413eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1414eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1415eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1416eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1417eee23b56SStefano Zampini         ncc++;
1418eee23b56SStefano Zampini         lc--;
1419eee23b56SStefano Zampini         cum++;
1420eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1421eee23b56SStefano Zampini       }
1422eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1423eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1424eee23b56SStefano Zampini       ncc++;
1425eee23b56SStefano Zampini     }
1426eee23b56SStefano Zampini     graph->ncc = ncc;
1427eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1428eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1429eee23b56SStefano Zampini     }
1430eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1431eee23b56SStefano Zampini   }
1432213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1433c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1434c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1435213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1436eee23b56SStefano Zampini 
1437c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1438a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1439a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1440b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1441b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1442a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1443a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1444a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1445a13144ffSStefano Zampini 
1446a13144ffSStefano Zampini   /* Complete assembling */
1447a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14481e0482f5SStefano Zampini   if (pcbddc->nedcG) {
14491e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14501e0482f5SStefano Zampini #if 0
14511e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14521e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14531e0482f5SStefano Zampini #endif
14541e0482f5SStefano Zampini   }
1455a13144ffSStefano Zampini 
1456a13144ffSStefano Zampini   /* set change of basis */
1457213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1458a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1459a13144ffSStefano Zampini 
1460a13144ffSStefano Zampini   PetscFunctionReturn(0);
1461a13144ffSStefano Zampini }
1462a13144ffSStefano Zampini 
1463d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1464d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1465d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1466d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1467d8203eabSStefano Zampini {
1468d8203eabSStefano Zampini   PetscErrorCode ierr;
1469d8203eabSStefano Zampini   PetscInt       i;
1470d8203eabSStefano Zampini 
1471d8203eabSStefano Zampini   PetscFunctionBegin;
1472d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1473d8203eabSStefano Zampini     PetscInt first,last;
1474d8203eabSStefano Zampini 
1475d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
147686fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1477d8203eabSStefano Zampini     if (i>=first && i < last) {
1478d8203eabSStefano Zampini       PetscScalar *data;
1479d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1480d8203eabSStefano Zampini       if (!has_const) {
1481d8203eabSStefano Zampini         data[i-first] = 1.;
1482d8203eabSStefano Zampini       } else {
148386fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
148486fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1485d8203eabSStefano Zampini       }
1486d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1487d8203eabSStefano Zampini     }
1488d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1489d8203eabSStefano Zampini   }
1490d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1491d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1492d8203eabSStefano Zampini     PetscInt first,last;
1493ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1494d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1495d8203eabSStefano Zampini     if (i>=first && i < last) {
1496d8203eabSStefano Zampini       PetscScalar *data;
1497d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1498d8203eabSStefano Zampini       if (!has_const) {
1499d8203eabSStefano Zampini         data[i-first] = 0.;
1500d8203eabSStefano Zampini       } else {
150186fa73c5SStefano Zampini         data[2*i-first] = 0.;
150286fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1503d8203eabSStefano Zampini       }
1504d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1505d8203eabSStefano Zampini     }
1506d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1507ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1508d8203eabSStefano Zampini   }
1509d8203eabSStefano Zampini   PetscFunctionReturn(0);
1510d8203eabSStefano Zampini }
1511d8203eabSStefano Zampini 
15128ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1513669cc0f4SStefano Zampini {
1514a198735bSStefano Zampini   Mat                    loc_divudotp;
1515fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
15168ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1517669cc0f4SStefano Zampini   PetscScalar            *vals;
1518669cc0f4SStefano Zampini   const PetscScalar      *array;
1519a040e873SStefano Zampini   PetscInt               i,maxneighs,maxsize;
1520a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
15211ae86dd6SStefano Zampini   PetscMPIInt            rank;
1522a198735bSStefano Zampini   PetscErrorCode         ierr;
1523669cc0f4SStefano Zampini 
1524669cc0f4SStefano Zampini   PetscFunctionBegin;
1525a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1526a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1527669cc0f4SStefano Zampini   maxsize = 0;
1528a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
1529669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1530669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1531669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
15328ae0ca82SStefano Zampini   if (!transpose) {
15338ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
15348ae0ca82SStefano Zampini   } else {
15358ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
15368ae0ca82SStefano Zampini   }
1537669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
15381ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1539d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1540669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1541ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
15428ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini   }
1544d8203eabSStefano Zampini 
1545669cc0f4SStefano Zampini   /* compute local quad vec */
1546a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15478ae0ca82SStefano Zampini   if (!transpose) {
1548a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15498ae0ca82SStefano Zampini   } else {
15508ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15518ae0ca82SStefano Zampini   }
1552669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15538ae0ca82SStefano Zampini   if (!transpose) {
1554a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15558ae0ca82SStefano Zampini   } else {
15568ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15578ae0ca82SStefano Zampini   }
1558fa23a32eSStefano Zampini   if (vl2l) {
1559187c917aSStefano Zampini     Mat        lA;
1560187c917aSStefano Zampini     VecScatter sc;
1561187c917aSStefano Zampini 
1562187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1563187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
1564187c917aSStefano Zampini     ierr = VecScatterCreate(v,vl2l,vins,NULL,&sc);CHKERRQ(ierr);
1565187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1566187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1567187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1568fa23a32eSStefano Zampini   } else {
1569fa23a32eSStefano Zampini     vins = v;
1570fa23a32eSStefano Zampini   }
1571fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1572669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15739a962809SStefano Zampini 
15741ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15751ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1576a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) {
1577669cc0f4SStefano Zampini     const PetscInt    *idxs;
1578669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1579669cc0f4SStefano Zampini 
1580a040e873SStefano Zampini     idxs = shared[i];
1581a040e873SStefano Zampini     nn   = n_shared[i];
1582669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15831ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1584669cc0f4SStefano Zampini     idx  = -(idx+1);
1585669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1586669cc0f4SStefano Zampini   }
1587a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1588fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1589fa23a32eSStefano Zampini   if (vl2l) {
1590187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1591fa23a32eSStefano Zampini   }
1592669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1593669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1594669cc0f4SStefano Zampini 
1595669cc0f4SStefano Zampini   /* assemble near null space */
1596669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1597669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1598669cc0f4SStefano Zampini   }
1599669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1600669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
16013272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
1602ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1603669cc0f4SStefano Zampini   }
1604669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1605669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1606669cc0f4SStefano Zampini }
1607669cc0f4SStefano Zampini 
16087620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
16097620a527SStefano Zampini {
16107620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16117620a527SStefano Zampini   PetscErrorCode ierr;
16127620a527SStefano Zampini 
16137620a527SStefano Zampini   PetscFunctionBegin;
16147620a527SStefano Zampini   if (primalv) {
16157620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
16167620a527SStefano Zampini       IS list[2], newp;
16177620a527SStefano Zampini 
16187620a527SStefano Zampini       list[0] = primalv;
16197620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
16207620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
16217620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
16227620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
16237620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
16247620a527SStefano Zampini     } else {
16257620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
16267620a527SStefano Zampini     }
16277620a527SStefano Zampini   }
16287620a527SStefano Zampini   PetscFunctionReturn(0);
16297620a527SStefano Zampini }
1630669cc0f4SStefano Zampini 
16311f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
16321f4df5f7SStefano Zampini {
16331f4df5f7SStefano Zampini   PetscErrorCode ierr;
16341f4df5f7SStefano Zampini   Vec            local,global;
16351f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16361f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
16375c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
16381f4df5f7SStefano Zampini 
16391f4df5f7SStefano Zampini   PetscFunctionBegin;
16405c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
16415c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16425c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16431f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
164421ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16451f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16466a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16476a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16486a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16496a8fc67bSStefano Zampini     }
16506a8fc67bSStefano Zampini     goto boundary;
16516a8fc67bSStefano Zampini   }
16525c5e10d6SStefano Zampini 
16531f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16541f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16551f4df5f7SStefano Zampini       PetscInt i;
16561f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16571f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16581f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16591f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16601f4df5f7SStefano Zampini       }
16611f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16621f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16631f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16641f4df5f7SStefano Zampini     }
16651f4df5f7SStefano Zampini   } else {
166621ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
166721ef3d20SStefano Zampini       DM dm;
166821ef3d20SStefano Zampini 
166921ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
167021ef3d20SStefano Zampini       if (!dm) {
167121ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
167221ef3d20SStefano Zampini       }
167321ef3d20SStefano Zampini       if (dm) {
167421ef3d20SStefano Zampini         IS      *fields;
167521ef3d20SStefano Zampini         PetscInt nf,i;
167621ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
167721ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
167821ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
167921ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
168021ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
168121ef3d20SStefano Zampini         }
168221ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
168321ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
168421ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
168521ef3d20SStefano Zampini         PetscContainer   c;
168621ef3d20SStefano Zampini 
168721ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
168821ef3d20SStefano Zampini         if (c) {
168921ef3d20SStefano Zampini           MatISLocalFields lf;
169021ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
169121ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
169221ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16931f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1694986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
169521ef3d20SStefano Zampini           if (i > 1) {
1696986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16971f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16981f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16991f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
17001f4df5f7SStefano Zampini             }
17011f4df5f7SStefano Zampini           }
170221ef3d20SStefano Zampini         }
170321ef3d20SStefano Zampini       }
17047a0e7b2cSstefano_zampini     } else {
17057a0e7b2cSstefano_zampini       PetscInt i;
17067a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
17077a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
17087a0e7b2cSstefano_zampini       }
17091f4df5f7SStefano Zampini     }
1710986cdee1SStefano Zampini   }
17111f4df5f7SStefano Zampini 
17125c5e10d6SStefano Zampini boundary:
17131f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
17141f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17157a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
17167a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17171f4df5f7SStefano Zampini   }
17181f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
17191f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17207a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
17217a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17221f4df5f7SStefano Zampini   }
17231f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
17241f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
17251f4df5f7SStefano Zampini   }
17261f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
17271f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
17287620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
17297620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
17307620a527SStefano Zampini     IS       primalv = NULL;
17317620a527SStefano Zampini     PetscInt i;
17327a0e7b2cSstefano_zampini 
17337620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17347620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17357620a527SStefano Zampini     }
17367620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17377620a527SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17387620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17397620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17407620a527SStefano Zampini   }
17417620a527SStefano Zampini   /* early stage corner detection */
17427620a527SStefano Zampini   {
17437620a527SStefano Zampini     DM dm;
17447620a527SStefano Zampini 
17457620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17467620a527SStefano Zampini     if (dm) {
17477620a527SStefano Zampini       PetscBool isda;
17487620a527SStefano Zampini 
17497620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17507620a527SStefano Zampini       if (isda) {
17517620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17527620a527SStefano Zampini         IS                     corners;
17537620a527SStefano Zampini         Mat                    lA;
17547620a527SStefano Zampini 
1755d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17567620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17577620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17587620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17597620a527SStefano Zampini         if (l2l) {
17607620a527SStefano Zampini           const PetscInt *idx;
17617620a527SStefano Zampini           PetscInt       bs,*idxout,n;
17627620a527SStefano Zampini 
17637620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17647620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17657620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
17667620a527SStefano Zampini           ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17677620a527SStefano Zampini           ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
17687620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1769d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17707620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17717620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17727620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17737620a527SStefano Zampini         } else { /* not from DMDA */
1774d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17757620a527SStefano Zampini         }
17767620a527SStefano Zampini       }
17777620a527SStefano Zampini     }
17787620a527SStefano Zampini   }
17797a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
17807a0e7b2cSstefano_zampini }
17817a0e7b2cSstefano_zampini 
17827a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
17837a0e7b2cSstefano_zampini {
17847a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
17857a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
17867a0e7b2cSstefano_zampini   IS              nis;
17877a0e7b2cSstefano_zampini   const PetscInt  *idxs;
17887a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
17897a0e7b2cSstefano_zampini   PetscBool       *ld;
17907a0e7b2cSstefano_zampini 
17917a0e7b2cSstefano_zampini   PetscFunctionBegin;
17927a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
17937a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
17947a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
17957a0e7b2cSstefano_zampini     /* init rootdata with true */
17967a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
17977a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
17987a0e7b2cSstefano_zampini   } else {
17997a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
18007a0e7b2cSstefano_zampini   }
18017a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18027a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18037a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18047a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18057a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18067a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18077a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18087a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18097a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18107a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18117a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18127a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18137a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18147a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18157a0e7b2cSstefano_zampini   } else {
18167a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18177a0e7b2cSstefano_zampini   }
18187a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18197a0e7b2cSstefano_zampini     if (ld[i])
18207a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18217a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18227a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18237a0e7b2cSstefano_zampini   *is  = nis;
18241f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18251f4df5f7SStefano Zampini }
18261f4df5f7SStefano Zampini 
18273e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18283e589ea0SStefano Zampini {
18293e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18303e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18313e589ea0SStefano Zampini   PetscErrorCode    ierr;
18323e589ea0SStefano Zampini 
18333e589ea0SStefano Zampini   PetscFunctionBegin;
18343e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18353e589ea0SStefano Zampini     PetscFunctionReturn(0);
18363e589ea0SStefano Zampini   }
18373e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18383e589ea0SStefano Zampini     Vec swap;
18393e589ea0SStefano Zampini 
18403e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18413e589ea0SStefano Zampini     swap = pcbddc->work_change;
18423e589ea0SStefano Zampini     pcbddc->work_change = r;
18433e589ea0SStefano Zampini     r = swap;
18443e589ea0SStefano Zampini   }
18453e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18463e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18473e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18483e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18493e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18503e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18513e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1852f913dca9SStefano Zampini     pcbddc->work_change = r;
18533e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18543e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18553e589ea0SStefano Zampini   }
18563e589ea0SStefano Zampini   PetscFunctionReturn(0);
18573e589ea0SStefano Zampini }
18583e589ea0SStefano Zampini 
1859a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1860a3df083aSStefano Zampini {
1861a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1862a3df083aSStefano Zampini   PetscErrorCode          ierr;
1863a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1864a3df083aSStefano Zampini 
1865a3df083aSStefano Zampini   PetscFunctionBegin;
1866a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1867a3df083aSStefano Zampini   if (transpose) {
1868a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1869a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1870a3df083aSStefano Zampini   } else {
1871a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1872a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1873a3df083aSStefano Zampini   }
1874a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1875a3df083aSStefano Zampini   if (apply_right) {
1876a3df083aSStefano Zampini     const PetscScalar *ax;
1877a3df083aSStefano Zampini     PetscInt          nl,i;
1878a3df083aSStefano Zampini 
1879a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1880a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1881a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1882a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1883a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1884a3df083aSStefano Zampini       PetscScalar    sum,val;
1885a3df083aSStefano Zampini       const PetscInt *idxs;
1886a3df083aSStefano Zampini       PetscInt       nz,j;
1887a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1888a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1889a3df083aSStefano Zampini       sum = 0.;
1890a3df083aSStefano Zampini       if (ctx->apply_p0) {
1891a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1892a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1893a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1894a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1895a3df083aSStefano Zampini         }
1896a3df083aSStefano Zampini       } else {
1897a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1898a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1899a3df083aSStefano Zampini         }
1900a3df083aSStefano Zampini       }
1901a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1902a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1903a3df083aSStefano Zampini     }
1904a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1905a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1906a3df083aSStefano Zampini   }
1907a3df083aSStefano Zampini   if (transpose) {
1908a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1909a3df083aSStefano Zampini   } else {
1910a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1911a3df083aSStefano Zampini   }
1912a3df083aSStefano Zampini   if (reset_x) {
1913a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1914a3df083aSStefano Zampini   }
1915a3df083aSStefano Zampini   if (apply_left) {
1916a3df083aSStefano Zampini     PetscScalar *ay;
1917a3df083aSStefano Zampini     PetscInt    i;
1918a3df083aSStefano Zampini 
1919a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1920a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1921a3df083aSStefano Zampini       PetscScalar    sum,val;
1922a3df083aSStefano Zampini       const PetscInt *idxs;
1923a3df083aSStefano Zampini       PetscInt       nz,j;
1924a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1925a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1926a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1927a3df083aSStefano Zampini       if (ctx->apply_p0) {
1928a3df083aSStefano Zampini         sum = 0.;
1929a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1930a3df083aSStefano Zampini           sum += ay[idxs[j]];
1931a3df083aSStefano Zampini           ay[idxs[j]] += val;
1932a3df083aSStefano Zampini         }
1933a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1934a3df083aSStefano Zampini       } else {
1935a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1936a3df083aSStefano Zampini           ay[idxs[j]] += val;
1937a3df083aSStefano Zampini         }
1938a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1939a3df083aSStefano Zampini       }
1940a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1941a3df083aSStefano Zampini     }
1942a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1943a3df083aSStefano Zampini   }
1944a3df083aSStefano Zampini   PetscFunctionReturn(0);
1945a3df083aSStefano Zampini }
1946a3df083aSStefano Zampini 
1947a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1948a3df083aSStefano Zampini {
1949a3df083aSStefano Zampini   PetscErrorCode ierr;
1950a3df083aSStefano Zampini 
1951a3df083aSStefano Zampini   PetscFunctionBegin;
1952a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1953a3df083aSStefano Zampini   PetscFunctionReturn(0);
1954a3df083aSStefano Zampini }
1955a3df083aSStefano Zampini 
1956a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1957a3df083aSStefano Zampini {
1958a3df083aSStefano Zampini   PetscErrorCode ierr;
1959a3df083aSStefano Zampini 
1960a3df083aSStefano Zampini   PetscFunctionBegin;
1961a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1962a3df083aSStefano Zampini   PetscFunctionReturn(0);
1963a3df083aSStefano Zampini }
1964a3df083aSStefano Zampini 
1965a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1966a3df083aSStefano Zampini {
1967a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1968a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1969a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1970a3df083aSStefano Zampini   PetscErrorCode          ierr;
1971a3df083aSStefano Zampini 
1972a3df083aSStefano Zampini   PetscFunctionBegin;
1973a3df083aSStefano Zampini   if (!restore) {
19741dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1975a3df083aSStefano Zampini     PetscScalar        *work;
1976b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1977a3df083aSStefano Zampini 
19789a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
19799a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1980a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1981a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1982a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1983a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1984a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1985a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1986a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1987a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1988a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1989a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1990a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1991a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1992059032f7SStefano Zampini     if (reuse) {
1993a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
19941dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1995059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1996059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1997059032f7SStefano Zampini       PetscInt               i;
1998059032f7SStefano Zampini 
1999059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2000059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2001059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2002059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2003059032f7SStefano Zampini       }
2004059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20051dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2006059032f7SStefano Zampini     }
2007a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2008a3df083aSStefano Zampini     ctx->work = work;
2009a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2010a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2011a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2012a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2013a3df083aSStefano Zampini 
2014a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2015a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2016a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2017a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2018a3df083aSStefano Zampini   } else {
20191dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20201dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20211dd7afcfSStefano Zampini     }
2022a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2023a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2024a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20251dd7afcfSStefano Zampini     ctx->A = NULL;
20261dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20271dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20281dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20291dd7afcfSStefano Zampini     if (ctx->free) {
2030059032f7SStefano Zampini       PetscInt i;
20311dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2032059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2033059032f7SStefano Zampini       }
2034059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2035059032f7SStefano Zampini     }
2036a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2037a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2038a3df083aSStefano Zampini   }
2039a3df083aSStefano Zampini   PetscFunctionReturn(0);
2040a3df083aSStefano Zampini }
2041a3df083aSStefano Zampini 
2042a3df083aSStefano Zampini /* used just in bddc debug mode */
2043a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2044a3df083aSStefano Zampini {
2045a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2046a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2047a3df083aSStefano Zampini   Mat            An;
2048a3df083aSStefano Zampini   PetscErrorCode ierr;
2049a3df083aSStefano Zampini 
2050a3df083aSStefano Zampini   PetscFunctionBegin;
2051a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2052a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2053a3df083aSStefano Zampini   if (is1) {
20547dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2055a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2056a3df083aSStefano Zampini   } else {
2057a3df083aSStefano Zampini     *B = An;
2058a3df083aSStefano Zampini   }
2059a3df083aSStefano Zampini   PetscFunctionReturn(0);
2060a3df083aSStefano Zampini }
2061a3df083aSStefano Zampini 
20621cf9b237SStefano Zampini /* TODO: add reuse flag */
20631cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20641cf9b237SStefano Zampini {
20651cf9b237SStefano Zampini   Mat            Bt;
20661cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20671cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20681cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20691cf9b237SStefano Zampini   PetscBool      flg_row;
20701cf9b237SStefano Zampini   PetscErrorCode ierr;
20711cf9b237SStefano Zampini 
20721cf9b237SStefano Zampini   PetscFunctionBegin;
20731cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20741cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20751cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20761cf9b237SStefano Zampini   nnz = n;
20771cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20781cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
20791cf9b237SStefano Zampini   }
20801cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
20811cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
20821cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
20831cf9b237SStefano Zampini   nnz = 0;
20841cf9b237SStefano Zampini   bii[0] = 0;
20851cf9b237SStefano Zampini   for (i=0;i<n;i++) {
20861cf9b237SStefano Zampini     PetscInt j;
20871cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
20881cf9b237SStefano Zampini       PetscScalar entry = a[j];
20893272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
20901cf9b237SStefano Zampini         bij[nnz] = ij[j];
20911cf9b237SStefano Zampini         bdata[nnz] = entry;
20921cf9b237SStefano Zampini         nnz++;
20931cf9b237SStefano Zampini       }
20941cf9b237SStefano Zampini     }
20951cf9b237SStefano Zampini     bii[i+1] = nnz;
20961cf9b237SStefano Zampini   }
20971cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
20981cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
20991cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21001cf9b237SStefano Zampini   {
21011cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21021cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21031cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21041cf9b237SStefano Zampini   }
21053272d46bSStefano Zampini   if (*B == A) {
21063272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21073272d46bSStefano Zampini   }
21081cf9b237SStefano Zampini   *B = Bt;
21091cf9b237SStefano Zampini   PetscFunctionReturn(0);
21101cf9b237SStefano Zampini }
21111cf9b237SStefano Zampini 
2112c80a6c00SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscInt *ncc, IS* cc[], IS* primalv)
21134f1b2e48SStefano Zampini {
2114c80a6c00SStefano Zampini   Mat                    B = NULL;
2115c80a6c00SStefano Zampini   DM                     dm;
21164f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21174f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21184f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2119c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21204f1b2e48SStefano Zampini   PetscInt               i,n;
21214f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2122c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21234f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21244f1b2e48SStefano Zampini 
21254f1b2e48SStefano Zampini   PetscFunctionBegin;
2126a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2127a2eca866SStefano Zampini   if (cc) *cc = NULL;
2128a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2129c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2130c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2131c80a6c00SStefano Zampini   if (!dm) {
2132c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2133c80a6c00SStefano Zampini   }
2134c80a6c00SStefano Zampini   if (dm) {
2135c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2136c80a6c00SStefano Zampini   }
2137c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2138c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2139c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2140c80a6c00SStefano Zampini     IS             cellNumbering;
2141c80a6c00SStefano Zampini     const PetscInt *cellNum;
2142c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2143c80a6c00SStefano Zampini     PetscSection   section;
2144c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2145c80a6c00SStefano Zampini     PetscSF        sfPoint;
2146c80a6c00SStefano Zampini     PetscErrorCode ierr;
2147c80a6c00SStefano Zampini 
2148c80a6c00SStefano Zampini     PetscFunctionBegin;
2149c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2150c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2151c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2152c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2153c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2154c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2155c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2156c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2157c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2158c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2159c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2160c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2161956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2162c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2163c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2164c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2165c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2166c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2167c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2168c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2169c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21705cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2171c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2172c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2173c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2174c80a6c00SStefano Zampini           *pBuf = point;
2175c80a6c00SStefano Zampini         }
2176c80a6c00SStefano Zampini       }
2177c80a6c00SStefano Zampini       n++;
2178c80a6c00SStefano Zampini     }
2179c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2180c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2181c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2182c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2183c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2184c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2185c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2186c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2187c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2188c80a6c00SStefano Zampini     }
2189c80a6c00SStefano Zampini     xadj[n] = size;
2190c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2191c80a6c00SStefano Zampini     /* Clean up */
2192c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2193c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2194c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2195c80a6c00SStefano Zampini     graph->xadj = xadj;
2196c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2197c80a6c00SStefano Zampini   } else {
2198c80a6c00SStefano Zampini     Mat       A;
2199c80a6c00SStefano Zampini     PetscBool filter = PETSC_FALSE, isseqaij, flg_row;
2200c80a6c00SStefano Zampini 
2201c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
220263c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2203a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
220463c961adSStefano Zampini       PetscFunctionReturn(0);
220563c961adSStefano Zampini     }
22064f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22074f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22081cf9b237SStefano Zampini       PetscBool isseqdense;
22091cf9b237SStefano Zampini 
22101cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22111cf9b237SStefano Zampini       if (!isseqdense) {
22124f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22131cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22141cf9b237SStefano Zampini         PetscScalar *array;
22151cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22161cf9b237SStefano Zampini 
22171cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22181cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22191cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22201cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22211cf9b237SStefano Zampini           PetscInt j;
22221cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22231cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22241cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22251cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22261cf9b237SStefano Zampini           }
22271cf9b237SStefano Zampini         }
22281cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22299d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22301cf9b237SStefano Zampini       }
22314f1b2e48SStefano Zampini     } else {
2232c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22334f1b2e48SStefano Zampini       B = A;
22344f1b2e48SStefano Zampini     }
22354f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22364f1b2e48SStefano Zampini 
22374f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22384f1b2e48SStefano Zampini     if (filter) {
22394f1b2e48SStefano Zampini       PetscScalar *data;
22404f1b2e48SStefano Zampini       PetscInt    j,cum;
22414f1b2e48SStefano Zampini 
22424f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22434f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22444f1b2e48SStefano Zampini       cum = 0;
22454f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22464f1b2e48SStefano Zampini         PetscInt t;
22474f1b2e48SStefano Zampini 
22484f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22494f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22504f1b2e48SStefano Zampini             continue;
22514f1b2e48SStefano Zampini           }
22524f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22534f1b2e48SStefano Zampini         }
22544f1b2e48SStefano Zampini         t = xadj_filtered[i];
22554f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22564f1b2e48SStefano Zampini         cum += t;
22574f1b2e48SStefano Zampini       }
22584f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22594f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22604f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22614f1b2e48SStefano Zampini     } else {
22624f1b2e48SStefano Zampini       graph->xadj = xadj;
22634f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22644f1b2e48SStefano Zampini     }
2265c80a6c00SStefano Zampini   }
2266c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2267c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2268c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2269c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2270c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2271c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22724f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22734f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2274c80a6c00SStefano Zampini 
22754f1b2e48SStefano Zampini   /* partial clean up */
22764f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2277c80a6c00SStefano Zampini   if (B) {
2278c80a6c00SStefano Zampini     PetscBool flg_row;
22794f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22804f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
22814f1b2e48SStefano Zampini   }
2282c80a6c00SStefano Zampini   if (isplex) {
2283c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2284c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2285c80a6c00SStefano Zampini   }
22864f1b2e48SStefano Zampini 
22874f1b2e48SStefano Zampini   /* get back data */
2288c80a6c00SStefano Zampini   if (isplex) {
2289c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2290c80a6c00SStefano Zampini     if (cc || primalv) {
2291c80a6c00SStefano Zampini       Mat          A;
2292c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2293c80a6c00SStefano Zampini       PetscSection subSection;
2294c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2295c80a6c00SStefano Zampini 
2296c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2297c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2298c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2299c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2300c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2301c80a6c00SStefano Zampini 
2302c80a6c00SStefano Zampini       cids[0] = 0;
2303c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2304c80a6c00SStefano Zampini         PetscInt j;
2305c80a6c00SStefano Zampini 
2306c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2307c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2308c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2309c80a6c00SStefano Zampini 
2310c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2311c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2312c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2313c80a6c00SStefano Zampini 
2314c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2315c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2316c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2317c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2318c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2319c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2320c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2321c80a6c00SStefano Zampini               } else { /* cross-vertex */
2322c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2323c80a6c00SStefano Zampini               }
2324c80a6c00SStefano Zampini             }
2325c80a6c00SStefano Zampini           }
2326c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2327c80a6c00SStefano Zampini         }
2328c80a6c00SStefano Zampini         cids[i+1] = cum;
2329c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2330c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2331c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2332c80a6c00SStefano Zampini         }
2333c80a6c00SStefano Zampini       }
2334c80a6c00SStefano Zampini       if (cc) {
2335c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2336c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2337c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2338c80a6c00SStefano Zampini         }
2339c80a6c00SStefano Zampini         *cc = cc_n;
2340c80a6c00SStefano Zampini       }
2341c80a6c00SStefano Zampini       if (primalv) {
2342c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2343c80a6c00SStefano Zampini       }
2344c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2345c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2346c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2347c80a6c00SStefano Zampini     }
2348c80a6c00SStefano Zampini   } else {
23491cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23501cf9b237SStefano Zampini     if (cc) {
23514f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23524f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23534f1b2e48SStefano 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);
23544f1b2e48SStefano Zampini       }
23554f1b2e48SStefano Zampini       *cc = cc_n;
23561cf9b237SStefano Zampini     }
2357c80a6c00SStefano Zampini   }
23584f1b2e48SStefano Zampini   /* clean up graph */
23594f1b2e48SStefano Zampini   graph->xadj = 0;
23604f1b2e48SStefano Zampini   graph->adjncy = 0;
23614f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23624f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23634f1b2e48SStefano Zampini }
23644f1b2e48SStefano Zampini 
23655408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23665408967cSStefano Zampini {
23675408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23685408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2369dee84bffSStefano Zampini   IS             dirIS = NULL;
23704f1b2e48SStefano Zampini   PetscInt       i;
23715408967cSStefano Zampini   PetscErrorCode ierr;
23725408967cSStefano Zampini 
23735408967cSStefano Zampini   PetscFunctionBegin;
2374dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
23755408967cSStefano Zampini   if (zerodiag) {
23765408967cSStefano Zampini     Mat            A;
23775408967cSStefano Zampini     Vec            vec3_N;
23785408967cSStefano Zampini     PetscScalar    *vals;
23795408967cSStefano Zampini     const PetscInt *idxs;
2380d12d3064SStefano Zampini     PetscInt       nz,*count;
23815408967cSStefano Zampini 
23825408967cSStefano Zampini     /* p0 */
23835408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
23845408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
23855408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
23865408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
23874f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
23885408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23895408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
23905408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
23915408967cSStefano Zampini     /* v_I */
23925408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
23935408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
23945408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23955408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
23965408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
23975408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
23985408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
23995408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24005408967cSStefano Zampini     if (dirIS) {
24015408967cSStefano Zampini       PetscInt n;
24025408967cSStefano Zampini 
24035408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24045408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24055408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24065408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24075408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24085408967cSStefano Zampini     }
24095408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24105408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24115408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24125408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2413669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24145408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24155408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24169a962809SStefano 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]));
24175408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24185408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2419d12d3064SStefano Zampini 
2420d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2421d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2422d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2423d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2424d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2425d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24269a962809SStefano 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]);
2427d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2428d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24295408967cSStefano Zampini   }
2430dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24315408967cSStefano Zampini 
24325408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24335408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24344f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24355408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24364f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24375408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2438f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2439f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
244013903a91SSatish 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);
2441f2a566d8SStefano Zampini   }
24425408967cSStefano Zampini   PetscFunctionReturn(0);
24435408967cSStefano Zampini }
24445408967cSStefano Zampini 
2445339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2446339f8db1SStefano Zampini {
2447339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24484edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2449b0f5fe93SStefano Zampini   PetscInt       nz,n;
24504edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24514edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2452339f8db1SStefano Zampini   PetscErrorCode ierr;
2453339f8db1SStefano Zampini 
2454339f8db1SStefano Zampini   PetscFunctionBegin;
24559f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24569f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2457a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2458a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2459a3df083aSStefano Zampini   }
2460a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2461a3df083aSStefano Zampini   pcbddc->benign_n = 0;
246228b8efb1Sstefano_zampini 
246328b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
24644f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
24654f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24664f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24671ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24684f1b2e48SStefano Zampini   */
24694f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
24704f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
247140fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24727fbe2174Sstefano_zampini     IS       iP = NULL;
24734f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
24744f1b2e48SStefano Zampini 
247528b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
247628b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
247728b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
247828b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
24794f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
24804f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
24814f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24824f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2483ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24847fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
24857fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
24867fbe2174Sstefano_zampini     if (iP) {
24877fbe2174Sstefano_zampini       IS newpressures;
24887fbe2174Sstefano_zampini 
24897fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
24907fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
24917fbe2174Sstefano_zampini       pressures = newpressures;
24927fbe2174Sstefano_zampini     }
249340fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
249440fa8d13SStefano Zampini     if (!sorted) {
249540fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
249640fa8d13SStefano Zampini     }
249740fa8d13SStefano Zampini   } else {
249840fa8d13SStefano Zampini     pressures = NULL;
249940fa8d13SStefano Zampini   }
250097d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
250197d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
250227b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
250397d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2504339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2505339f8db1SStefano Zampini   if (!sorted) {
2506339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2507339f8db1SStefano Zampini   }
25084edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25094edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2510339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25114f1b2e48SStefano Zampini   if (!nz) {
25124f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25134f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
251440fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
251540fa8d13SStefano Zampini   }
25164f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25174f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25184f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25194f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
25201f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25211f4df5f7SStefano Zampini   interior_dofs    = NULL;
25224edc6404Sstefano_zampini   nneu             = 0;
25234edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25244edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25254edc6404Sstefano_zampini   }
25263369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25274edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25281f4df5f7SStefano Zampini     PetscInt n,i,j;
25291f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25301f4df5f7SStefano Zampini     PetscInt *iwork;
25311f4df5f7SStefano Zampini 
25321f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25331f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25341f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25351f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
253690648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25371f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25381f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25391f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25401f4df5f7SStefano Zampini       if (!iwork[i])
25411f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25421f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25431f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25441f4df5f7SStefano Zampini   }
25454f1b2e48SStefano Zampini   if (has_null_pressures) {
25464f1b2e48SStefano Zampini     IS             *subs;
25474edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
25481f4df5f7SStefano Zampini     const PetscInt *idxs;
25491f4df5f7SStefano Zampini     PetscScalar    *array;
25501f4df5f7SStefano Zampini     Vec            *work;
25511f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25524f1b2e48SStefano Zampini 
25534f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
25544f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
25551f4df5f7SStefano 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) */
25564edc6404Sstefano_zampini     if (checkb) {
25571f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
25581f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
25591f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25601f4df5f7SStefano Zampini       /* work[0] = 1_p */
25611f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
25621f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
25631f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25641f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
25651f4df5f7SStefano Zampini       /* work[0] = 1_v */
25661f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
25671f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
25681f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
25691f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
25701f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
25711f4df5f7SStefano Zampini     }
25724f1b2e48SStefano Zampini     if (nsubs > 1) {
25734f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
25744f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
25754f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
25764f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
25774f1b2e48SStefano Zampini         PetscInt               nl;
25784f1b2e48SStefano Zampini 
25794f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
25804f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
25814f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
25824f1b2e48SStefano Zampini         if (nl) {
25834f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
25844f1b2e48SStefano Zampini 
25854edc6404Sstefano_zampini           if (checkb) {
25861f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
25871f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
25881f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
25891f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
25901f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25911f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
25921f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
25931f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
25941f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
25951f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
25961f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
25971f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
25981f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
25991f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
26001f4df5f7SStefano Zampini                 break;
26011f4df5f7SStefano Zampini               }
26021f4df5f7SStefano Zampini             }
26031f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26041f4df5f7SStefano Zampini           }
26056632bad2Sstefano_zampini           if (valid && nneu) {
26066632bad2Sstefano_zampini             const PetscInt *idxs;
26071f4df5f7SStefano Zampini             PetscInt       nzb;
26081f4df5f7SStefano Zampini 
26096632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26106632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26116632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26121f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
26131f4df5f7SStefano Zampini           }
26141f4df5f7SStefano Zampini           if (valid && pressures) {
26154f1b2e48SStefano Zampini             IS t_pressure_subs;
26164f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26174f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
26184f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26194f1b2e48SStefano Zampini           }
26204f1b2e48SStefano Zampini           if (valid) {
26214f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
26224f1b2e48SStefano Zampini             pcbddc->benign_n++;
26234f1b2e48SStefano Zampini           } else {
26244f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
26254f1b2e48SStefano Zampini           }
26264f1b2e48SStefano Zampini         }
26274f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
26284f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
26294f1b2e48SStefano Zampini       }
26304f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
26314f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
26321f4df5f7SStefano Zampini 
26336632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
26341f4df5f7SStefano Zampini       if (valid && pressures) {
26354f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
26364f1b2e48SStefano Zampini       }
26374edc6404Sstefano_zampini       if (valid && checkb) {
26381f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
26391f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
26401f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26411f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
26421f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26431f4df5f7SStefano Zampini             valid = PETSC_FALSE;
26441f4df5f7SStefano Zampini             break;
26451f4df5f7SStefano Zampini           }
26461f4df5f7SStefano Zampini         }
26471f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26481f4df5f7SStefano Zampini       }
26494f1b2e48SStefano Zampini       if (valid) {
26504f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2651ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
26524f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26534f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
26544f1b2e48SStefano Zampini       }
26554f1b2e48SStefano Zampini     }
26564edc6404Sstefano_zampini     if (checkb) {
26571f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
26584f1b2e48SStefano Zampini     }
26591f4df5f7SStefano Zampini   }
26601f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
26614f1b2e48SStefano Zampini 
26624f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2663b9b0e38cSStefano Zampini     PetscInt n;
2664b9b0e38cSStefano Zampini 
26654f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26664f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2667b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2668b9b0e38cSStefano Zampini     if (n) {
26694f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
26704f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
26714f1b2e48SStefano Zampini     }
2672b9b0e38cSStefano Zampini   }
26734f1b2e48SStefano Zampini 
26744f1b2e48SStefano Zampini   /* final check for null pressures */
26754f1b2e48SStefano Zampini   if (zerodiag && pressures) {
26764f1b2e48SStefano Zampini     PetscInt nz,np;
26774f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26784f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
26794f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
26804f1b2e48SStefano Zampini   }
26814f1b2e48SStefano Zampini 
26824f1b2e48SStefano Zampini   if (recompute_zerodiag) {
26834f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26844f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
26854f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
26864f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
26874f1b2e48SStefano Zampini     } else {
26884f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
26894f1b2e48SStefano Zampini 
26904f1b2e48SStefano Zampini       nzn = 0;
26914f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26924f1b2e48SStefano Zampini         PetscInt ns;
26934f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
26944f1b2e48SStefano Zampini         nzn += ns;
26954f1b2e48SStefano Zampini       }
26964f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
26974f1b2e48SStefano Zampini       nzn = 0;
26984f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26994f1b2e48SStefano Zampini         PetscInt ns,*idxs;
27004f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27014f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27024f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
27034f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini         nzn += ns;
27054f1b2e48SStefano Zampini       }
27064f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27074f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27084f1b2e48SStefano Zampini     }
27094f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27104f1b2e48SStefano Zampini   }
27114f1b2e48SStefano Zampini 
2712669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2713a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2714a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2715a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2716a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2717a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2718a198735bSStefano Zampini 
27191f4df5f7SStefano Zampini     if (pressures) {
27201f4df5f7SStefano Zampini       isused = pressures;
27211f4df5f7SStefano Zampini     } else {
27224edc6404Sstefano_zampini       isused = zerodiag_save;
27231f4df5f7SStefano Zampini     }
2724a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2725669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
27261ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
27271ae86dd6SStefano 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");
2728a198735bSStefano Zampini     n_isused = 0;
2729a198735bSStefano Zampini     if (isused) {
2730a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2731a198735bSStefano Zampini     }
2732a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2733a198735bSStefano Zampini     st = st-n_isused;
27341ae86dd6SStefano Zampini     if (n) {
2735a198735bSStefano Zampini       const PetscInt *gidxs;
2736a198735bSStefano Zampini 
27377dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2738a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2739a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2740a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2741a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2742a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
27431ae86dd6SStefano Zampini     } else {
2744a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2745a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2746a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2747a198735bSStefano Zampini     }
2748a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2749a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2750a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2751a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2752a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2753a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2754a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2755a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2756a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2757a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2758a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2759a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2760a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2761a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
27621ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27631ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27641ae86dd6SStefano Zampini   }
27654edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2766b3afcdbeSStefano Zampini 
2767b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
27684f1b2e48SStefano Zampini   if (has_null_pressures) {
27694f1b2e48SStefano Zampini     IS             zerodiagc;
27704f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
27714f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
27724f1b2e48SStefano Zampini 
27734f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2774339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2775339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2776339f8db1SStefano Zampini     /* local change of basis for pressures */
2777339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
277897d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2779339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2780339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2781339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
27824f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
27834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
27844f1b2e48SStefano Zampini       PetscInt nzs,j;
27854f1b2e48SStefano Zampini 
27864f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
27874f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27884f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
27894f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
27904f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
27914f1b2e48SStefano Zampini     }
2792339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2793339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2794339f8db1SStefano Zampini     /* set identity on velocities */
2795339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2796339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2797339f8db1SStefano Zampini     }
27984f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
27994f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
28009f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
28014f1b2e48SStefano 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);
2802339f8db1SStefano Zampini     /* set change on pressures */
28034f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28044f1b2e48SStefano Zampini       PetscScalar *array;
28054f1b2e48SStefano Zampini       PetscInt    nzs;
28064f1b2e48SStefano Zampini 
28074f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28084f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28094f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2810339f8db1SStefano Zampini         PetscScalar vals[2];
2811339f8db1SStefano Zampini         PetscInt    cols[2];
2812339f8db1SStefano Zampini 
2813339f8db1SStefano Zampini         cols[0] = idxs[i];
28144f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2815339f8db1SStefano Zampini         vals[0] = 1.;
2816b0f5fe93SStefano Zampini         vals[1] = 1.;
28174f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2818339f8db1SStefano Zampini       }
28194f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
28204f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
28214f1b2e48SStefano Zampini       array[nzs-1] = 1.;
28224f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
28234f1b2e48SStefano Zampini       /* store local idxs for p0 */
28244f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
28254f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2826339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
28274f1b2e48SStefano Zampini     }
2828339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2829339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2830a3df083aSStefano Zampini     /* project if needed */
2831a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28321dd7afcfSStefano Zampini       Mat M;
28331dd7afcfSStefano Zampini 
28341dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2835339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28361dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
28371dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2838a3df083aSStefano Zampini     }
28394f1b2e48SStefano Zampini     /* store global idxs for p0 */
28404f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2841339f8db1SStefano Zampini   }
2842ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28434f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2844b0f5fe93SStefano Zampini 
2845b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2846b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
284727b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
284827b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2849339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2850339f8db1SStefano Zampini   PetscFunctionReturn(0);
2851339f8db1SStefano Zampini }
2852339f8db1SStefano Zampini 
2853015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2854efc2fbd9SStefano Zampini {
2855efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2856de9d7bd0SStefano Zampini   PetscScalar    *array;
2857efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2858efc2fbd9SStefano Zampini 
2859efc2fbd9SStefano Zampini   PetscFunctionBegin;
2860efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2861efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
28624f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2863efc2fbd9SStefano Zampini   }
2864de9d7bd0SStefano Zampini   if (get) {
2865efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
28664f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
28674f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2868efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2869de9d7bd0SStefano Zampini   } else {
2870de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2871de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2872de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2873de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2874efc2fbd9SStefano Zampini   }
2875efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2876efc2fbd9SStefano Zampini }
2877efc2fbd9SStefano Zampini 
2878c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2879c263805aSStefano Zampini {
2880c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2881c263805aSStefano Zampini   PetscErrorCode ierr;
2882c263805aSStefano Zampini 
2883c263805aSStefano Zampini   PetscFunctionBegin;
2884c263805aSStefano Zampini   /* TODO: add error checking
2885c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2886c263805aSStefano Zampini     - cannot push before pop.
28871c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2888c263805aSStefano Zampini   */
28894f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2890efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2891efc2fbd9SStefano Zampini   }
2892c263805aSStefano Zampini   if (pop) {
2893a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28944f1b2e48SStefano Zampini       IS       is_p0;
28954f1b2e48SStefano Zampini       MatReuse reuse;
2896c263805aSStefano Zampini 
2897c263805aSStefano Zampini       /* extract B_0 */
28984f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
28994f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
29004f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
29014f1b2e48SStefano Zampini       }
29024f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
29037dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2904c263805aSStefano Zampini       /* remove rows and cols from local problem */
2905c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
290697d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29074f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29084f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2909a3df083aSStefano Zampini     } else {
2910a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2911a3df083aSStefano Zampini       PetscScalar *vals;
2912a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2913a3df083aSStefano Zampini 
2914a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2915a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2916a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
29170b5adadeSStefano Zampini         PetscInt *nnz;
2918a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2919a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2920a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2921331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2922331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2923331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2924331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2925331e053bSStefano Zampini         }
2926331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2927331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2928331e053bSStefano Zampini       }
2929a3df083aSStefano Zampini 
2930a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2931a3df083aSStefano Zampini         PetscScalar *array;
2932a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2933a3df083aSStefano Zampini 
2934a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2935a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2936a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2937a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2938a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2939a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2940a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2941a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2942a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2943a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2944a3df083aSStefano Zampini         cum = 0;
2945a3df083aSStefano Zampini         for (j=0;j<n;j++) {
294622db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2947a3df083aSStefano Zampini             vals[cum] = array[j];
2948a3df083aSStefano Zampini             idxs_ins[cum] = j;
2949a3df083aSStefano Zampini             cum++;
2950a3df083aSStefano Zampini           }
2951a3df083aSStefano Zampini         }
2952a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2953a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2954a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2955a3df083aSStefano Zampini       }
2956a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2957a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2958a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2959a3df083aSStefano Zampini     }
2960c263805aSStefano Zampini   } else { /* push */
2961a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29624f1b2e48SStefano Zampini       PetscInt i;
29634f1b2e48SStefano Zampini 
29644f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
29654f1b2e48SStefano Zampini         PetscScalar *B0_vals;
29664f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
29674f1b2e48SStefano Zampini 
29684f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29694f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29707b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29714f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
29724f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29734f1b2e48SStefano Zampini       }
2974c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2975c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2976a3df083aSStefano Zampini     } else {
2977a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2978a3df083aSStefano Zampini     }
2979c263805aSStefano Zampini   }
2980c263805aSStefano Zampini   PetscFunctionReturn(0);
2981c263805aSStefano Zampini }
2982c263805aSStefano Zampini 
298308122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2984b1b3d7a2SStefano Zampini {
2985b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
298608122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
298708122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
298808122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
298908122e43SStefano Zampini   PetscScalar     *work,lwork;
299008122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
299108122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
2992bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
29931b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2994f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
299508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
299608122e43SStefano Zampini   PetscReal       *rwork;
299708122e43SStefano Zampini #endif
2998b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2999b1b3d7a2SStefano Zampini 
3000b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3001b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3002af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3003bd2a564bSStefano 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);
300406a4e24aSStefano Zampini 
3005fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3006fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3007fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3008fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30091575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3010fd14bc51SStefano Zampini   }
3011fd14bc51SStefano Zampini 
3012e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
3013e496cd5dSStefano 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);
3014e496cd5dSStefano Zampini   }
3015e496cd5dSStefano Zampini 
301608122e43SStefano Zampini   /* max size of subsets */
301708122e43SStefano Zampini   mss = 0;
301808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
301908122e43SStefano Zampini     PetscInt subset_size;
3020862806e4SStefano Zampini 
302108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
302208122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
302308122e43SStefano Zampini   }
302408122e43SStefano Zampini 
302508122e43SStefano Zampini   /* min/max and threshold */
302608122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3027f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
302808122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3029f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3030bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3031f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3032f6f667cfSStefano Zampini   }
303308122e43SStefano Zampini 
303408122e43SStefano Zampini   /* allocate lapack workspace */
303508122e43SStefano Zampini   cum = cum2 = 0;
303608122e43SStefano Zampini   maxneigs = 0;
303708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
303808122e43SStefano Zampini     PetscInt n,subset_size;
3039f6f667cfSStefano Zampini 
304008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
304108122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
30429162d606SStefano Zampini     cum += subset_size;
30439162d606SStefano Zampini     cum2 += subset_size*n;
304408122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
304508122e43SStefano Zampini   }
304608122e43SStefano Zampini   if (mss) {
3047bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
304808122e43SStefano Zampini       PetscBLASInt B_itype = 1;
304908122e43SStefano Zampini       PetscBLASInt B_N = mss;
30504c6709b3SStefano Zampini       PetscReal    zero = 0.0;
30514c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
305208122e43SStefano Zampini 
305308122e43SStefano Zampini       B_lwork = -1;
305408122e43SStefano Zampini       S = NULL;
305508122e43SStefano Zampini       St = NULL;
3056a58a30b4SStefano Zampini       eigs = NULL;
3057a58a30b4SStefano Zampini       eigv = NULL;
3058a58a30b4SStefano Zampini       B_iwork = NULL;
3059a58a30b4SStefano Zampini       B_ifail = NULL;
3060d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3061d1710679SStefano Zampini       rwork = NULL;
3062d1710679SStefano Zampini #endif
30638bec7fa6SStefano Zampini       thresh = 1.0;
306408122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
306508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
306608122e43SStefano 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));
306708122e43SStefano Zampini #else
306808122e43SStefano 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));
306908122e43SStefano Zampini #endif
307008122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
307108122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3072bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
307308122e43SStefano Zampini   } else {
307408122e43SStefano Zampini     lwork = 0;
307508122e43SStefano Zampini   }
307608122e43SStefano Zampini 
307708122e43SStefano Zampini   nv = 0;
3078d62866d3SStefano 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) */
3079d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
308008122e43SStefano Zampini   }
30814c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3082f6f667cfSStefano Zampini   if (allocated_S_St) {
3083f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3084f6f667cfSStefano Zampini   }
3085f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
308608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
308708122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
308808122e43SStefano Zampini #endif
30899162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
30909162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
30919162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
309208122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
30939162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
309408122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
309508122e43SStefano Zampini 
309608122e43SStefano Zampini   maxneigs = 0;
309772b8c272SStefano Zampini   cum = cumarray = 0;
30989162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
30999162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3100d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
310108122e43SStefano Zampini     const PetscInt *idxs;
310208122e43SStefano Zampini 
3103d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
310408122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
310508122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
310608122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
310708122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31089162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31099162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
311008122e43SStefano Zampini     }
3111d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
311208122e43SStefano Zampini   }
311308122e43SStefano Zampini 
311408122e43SStefano Zampini   if (mss) { /* multilevel */
311508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
311608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
311708122e43SStefano Zampini   }
311808122e43SStefano Zampini 
3119bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3120bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
312108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
312208122e43SStefano Zampini     const PetscInt *idxs;
31239d54b7f4SStefano Zampini     PetscReal      upper,lower;
3124862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
312508122e43SStefano Zampini     PetscBLASInt   B_N;
3126aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3127bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
312808122e43SStefano Zampini 
31299d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
31309d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3131bd2a564bSStefano Zampini       lower = uthresh;
31329d54b7f4SStefano Zampini     } else {
3133bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3134bd2a564bSStefano Zampini       upper = 1./uthresh;
31359d54b7f4SStefano Zampini       lower = 0.;
31369d54b7f4SStefano Zampini     }
3137862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3138ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3139f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3140bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3141bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3142bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3143bd2a564bSStefano Zampini       Mat T;
3144bd2a564bSStefano Zampini 
3145bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3146bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3147bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3148bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3149bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3150bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3151bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3152bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3153bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3154bd2a564bSStefano Zampini             PetscInt       nz,k;
3155bd2a564bSStefano Zampini             const PetscInt *idxs;
3156bd2a564bSStefano Zampini 
3157bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3158bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3159bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3160bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3161bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3162bd2a564bSStefano Zampini             }
3163bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3164bd2a564bSStefano Zampini           }
3165bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3166bd2a564bSStefano Zampini           break;
3167bd2a564bSStefano Zampini         }
3168bd2a564bSStefano Zampini       }
3169bd2a564bSStefano Zampini     }
3170bd2a564bSStefano Zampini 
3171f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3172bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3173aff50787SStefano Zampini         PetscInt j,k;
3174aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3175aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3176aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
317708122e43SStefano Zampini         }
317808122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3179aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3180aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3181aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3182aff50787SStefano Zampini           }
318308122e43SStefano Zampini         }
318408122e43SStefano Zampini       } else {
318508122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
318608122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
318708122e43SStefano Zampini       }
31888bec7fa6SStefano Zampini     } else {
3189f6f667cfSStefano Zampini       S = Sarray + cumarray;
3190f6f667cfSStefano Zampini       St = Starray + cumarray;
31918bec7fa6SStefano Zampini     }
3192aff50787SStefano Zampini     /* see if we can save some work */
3193b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3194aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3195aff50787SStefano Zampini     }
3196aff50787SStefano Zampini 
3197b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3198aff50787SStefano Zampini       B_neigs = 0;
3199aff50787SStefano Zampini     } else {
3200bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
320108122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3202f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
32034c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
32049552c7c7SStefano Zampini         PetscInt     nmin_s;
3205bd2a564bSStefano Zampini         PetscBool    compute_range;
3206bd2a564bSStefano Zampini 
3207bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3208bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
320908122e43SStefano Zampini 
3210fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3211bd2a564bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d size %d count %d fid %d (range %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);CHKERRQ(ierr);
3212b7ab4a40SStefano Zampini         }
3213b7ab4a40SStefano Zampini 
321408122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3215b7ab4a40SStefano Zampini         if (compute_range) {
3216d16cbb6bSStefano Zampini 
3217d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3218bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
321908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32209d54b7f4SStefano 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));
322108122e43SStefano Zampini #else
32229d54b7f4SStefano 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));
322308122e43SStefano Zampini #endif
3224bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
3225bd2a564bSStefano Zampini             PetscInt  recipe = 0;
3226bd2a564bSStefano Zampini             PetscReal bb[2];
3227bd2a564bSStefano Zampini 
3228bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3229bd2a564bSStefano Zampini             switch (recipe) {
3230bd2a564bSStefano Zampini             case 0:
3231bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3232bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3233bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3234bd2a564bSStefano 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));
3235bd2a564bSStefano Zampini #else
3236bd2a564bSStefano 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));
3237bd2a564bSStefano Zampini #endif
3238bd2a564bSStefano Zampini               break;
3239bd2a564bSStefano Zampini             case 1:
3240bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3241bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3242bd2a564bSStefano 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));
3243bd2a564bSStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
3245bd2a564bSStefano Zampini #endif
3246bd2a564bSStefano Zampini               if (!scal) {
3247bd2a564bSStefano Zampini                 PetscBLASInt B_neigs2;
3248bd2a564bSStefano Zampini 
3249bd2a564bSStefano Zampini                 bb[0] = uthresh; bb[1] = PETSC_MAX_REAL;
3250bd2a564bSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3251bd2a564bSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3252bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3253bd2a564bSStefano 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));
3254bd2a564bSStefano Zampini #else
3255bd2a564bSStefano 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));
3256bd2a564bSStefano Zampini #endif
3257bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3258bd2a564bSStefano Zampini               }
3259bd2a564bSStefano Zampini               break;
3260bd2a564bSStefano Zampini             default:
3261bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3262bd2a564bSStefano Zampini               break;
3263bd2a564bSStefano Zampini             }
3264bd2a564bSStefano Zampini           }
3265bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3266d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3267d16cbb6bSStefano Zampini           B_IL = 1;
3268d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
32699d54b7f4SStefano 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));
3270d16cbb6bSStefano Zampini #else
32719d54b7f4SStefano 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));
3272d16cbb6bSStefano Zampini #endif
3273b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3274b7ab4a40SStefano Zampini           PetscInt k;
3275b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3276b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3277b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3278b7ab4a40SStefano Zampini           nmin = nmax;
3279b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3280b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3281b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3282b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3283b7ab4a40SStefano Zampini           }
3284d16cbb6bSStefano Zampini         }
328508122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
328608122e43SStefano Zampini         if (B_ierr) {
32876c4ed002SBarry 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);
32886c4ed002SBarry 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);
32896c4ed002SBarry 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);
329008122e43SStefano Zampini         }
329108122e43SStefano Zampini 
329208122e43SStefano Zampini         if (B_neigs > nmax) {
3293fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3294bd2a564bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);CHKERRQ(ierr);
3295fd14bc51SStefano Zampini           }
3296bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
329708122e43SStefano Zampini           B_neigs = nmax;
329808122e43SStefano Zampini         }
329908122e43SStefano Zampini 
33009552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
33019552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
330208122e43SStefano Zampini           PetscBLASInt B_neigs2;
330308122e43SStefano Zampini 
33049d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3305bd2a564bSStefano Zampini             if (scal) {
3306bd2a564bSStefano Zampini               B_IU = nmin_s;
3307bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3308bd2a564bSStefano Zampini             } else {
3309f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
33109d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3311bd2a564bSStefano Zampini             }
33129d54b7f4SStefano Zampini           } else {
33139d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
33149d54b7f4SStefano Zampini             B_IU = nmin_s;
33159d54b7f4SStefano Zampini           }
3316fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3317fd14bc51SStefano 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);
3318fd14bc51SStefano Zampini           }
3319bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
33201ae86dd6SStefano Zampini             PetscInt j,k;
332108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
33221ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
33231ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
33241ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
332508122e43SStefano Zampini               }
332608122e43SStefano Zampini             }
332708122e43SStefano Zampini           } else {
332808122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
332908122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
333008122e43SStefano Zampini           }
333108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
333208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33339d54b7f4SStefano 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));
333408122e43SStefano Zampini #else
33359d54b7f4SStefano 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));
333608122e43SStefano Zampini #endif
333708122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
333808122e43SStefano Zampini           B_neigs += B_neigs2;
333908122e43SStefano Zampini         }
334008122e43SStefano Zampini         if (B_ierr) {
33416c4ed002SBarry 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);
33426c4ed002SBarry 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);
33436c4ed002SBarry 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);
334408122e43SStefano Zampini         }
3345fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3346ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
334708122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
334808122e43SStefano Zampini             if (eigs[j] == 0.0) {
3349ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
335008122e43SStefano Zampini             } else {
33519d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3352ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
33539d54b7f4SStefano Zampini               } else {
33549d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
33559d54b7f4SStefano Zampini               }
3356fd14bc51SStefano Zampini             }
335708122e43SStefano Zampini           }
335808122e43SStefano Zampini         }
3359bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3360aff50787SStefano Zampini     }
33616c3e6151SStefano Zampini     /* change the basis back to the original one */
33626c3e6151SStefano Zampini     if (sub_schurs->change) {
336372b8c272SStefano Zampini       Mat change,phi,phit;
33646c3e6151SStefano Zampini 
336503dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
33666c3e6151SStefano Zampini         PetscInt ii;
33676c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
33686c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
33696c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3370684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3371684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3372684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3373684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3374684229deSStefano Zampini #else
33756c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3376684229deSStefano Zampini #endif
33776c3e6151SStefano Zampini           }
33786c3e6151SStefano Zampini         }
33796c3e6151SStefano Zampini       }
338072b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
33816c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
338272b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
33836c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
33846c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
33856c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
33866c3e6151SStefano Zampini     }
33878bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
33888bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
33899162d606SStefano Zampini     if (B_neigs) {
33909162d606SStefano 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);
3391fd14bc51SStefano Zampini 
3392fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
33939552c7c7SStefano Zampini         PetscInt ii;
33949552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3395ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
33969552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3397ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3398ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3399ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3400ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3401ac47001eSStefano Zampini #else
3402ac47001eSStefano 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);
3403ac47001eSStefano Zampini #endif
34049552c7c7SStefano Zampini           }
34059552c7c7SStefano Zampini         }
3406fd14bc51SStefano Zampini       }
34079162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
34089162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
34099162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
34109162d606SStefano Zampini       cum++;
341108122e43SStefano Zampini     }
341208122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
341308122e43SStefano Zampini     /* shift for next computation */
341408122e43SStefano Zampini     cumarray += subset_size*subset_size;
341508122e43SStefano Zampini   }
3416fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3417fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3418fd14bc51SStefano Zampini   }
341908122e43SStefano Zampini 
342008122e43SStefano Zampini   if (mss) {
342108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
342208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3423f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3424f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3425f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
342608122e43SStefano Zampini   }
3427f6f667cfSStefano Zampini   if (allocated_S_St) {
3428f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3429f6f667cfSStefano Zampini   }
3430f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
343108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
343208122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
343308122e43SStefano Zampini #endif
343408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
34351b968477SStefano Zampini     PetscInt maxneigs_r;
3436b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
34379b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
343808122e43SStefano Zampini   }
343908122e43SStefano Zampini   PetscFunctionReturn(0);
344008122e43SStefano Zampini }
3441b1b3d7a2SStefano Zampini 
3442c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3443c8587f34SStefano Zampini {
34448629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3445c8587f34SStefano Zampini   PetscErrorCode ierr;
3446c8587f34SStefano Zampini 
3447c8587f34SStefano Zampini   PetscFunctionBegin;
3448f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
34495e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3450c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3451c8587f34SStefano Zampini 
3452684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
34530fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3454684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3455c8587f34SStefano Zampini 
34568629588bSStefano Zampini   /*
34578629588bSStefano Zampini      Setup local correction and local part of coarse basis.
34588629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
34598629588bSStefano Zampini   */
346047f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
34618629588bSStefano Zampini 
34628629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
34638629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
34648629588bSStefano Zampini 
34658629588bSStefano Zampini   /* free */
34668629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3467c8587f34SStefano Zampini   PetscFunctionReturn(0);
3468c8587f34SStefano Zampini }
3469c8587f34SStefano Zampini 
3470674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3471674ae819SStefano Zampini {
3472674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3473674ae819SStefano Zampini   PetscErrorCode ierr;
3474674ae819SStefano Zampini 
3475674ae819SStefano Zampini   PetscFunctionBegin;
3476674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
347730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3478674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3479785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3480674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3481f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3482f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3483785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
348463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
348563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3486674ae819SStefano Zampini   PetscFunctionReturn(0);
3487674ae819SStefano Zampini }
3488674ae819SStefano Zampini 
3489674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3490674ae819SStefano Zampini {
3491674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
34924f1b2e48SStefano Zampini   PetscInt       i;
3493674ae819SStefano Zampini   PetscErrorCode ierr;
3494674ae819SStefano Zampini 
3495674ae819SStefano Zampini   PetscFunctionBegin;
34961e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
34971e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3498a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3499b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3500674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
350116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
35021dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3503674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3504669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3505fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
35069326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
35074f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
35084f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
35094f1b2e48SStefano Zampini   }
3510e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
35114f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3512e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3513c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
35148af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3515674ae819SStefano Zampini   PetscFunctionReturn(0);
3516674ae819SStefano Zampini }
3517674ae819SStefano Zampini 
3518674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3519674ae819SStefano Zampini {
3520674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3521674ae819SStefano Zampini   PetscErrorCode ierr;
3522674ae819SStefano Zampini 
3523674ae819SStefano Zampini   PetscFunctionBegin;
3524674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
352558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3526ca92afb2SStefano Zampini     PetscScalar *array;
352706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
352806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
352958da7f69SStefano Zampini   }
3530674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3531674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
353215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
353315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3534674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3535674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3536674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
353706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3538674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3539674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
35408ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3541674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3542674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3543674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
35449326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
35459326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
35469326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3547f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3548727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
35490e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3550f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
355170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
355281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
35530369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
35541dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
35554f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
35568b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3557ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3558ca92afb2SStefano Zampini     PetscInt i;
3559ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3560ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3561ca92afb2SStefano Zampini     }
3562ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3563ca92afb2SStefano Zampini   }
35644f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3565674ae819SStefano Zampini   PetscFunctionReturn(0);
3566674ae819SStefano Zampini }
3567674ae819SStefano Zampini 
3568f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
35696bfb1811SStefano Zampini {
35706bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
35716bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
35726bfb1811SStefano Zampini   VecType        impVecType;
35734f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
35746bfb1811SStefano Zampini   PetscErrorCode ierr;
35756bfb1811SStefano Zampini 
35766bfb1811SStefano Zampini   PetscFunctionBegin;
35774f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3578b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
35796bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3580e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3581e7b262bdSStefano Zampini   /* R nodes */
3582e7b262bdSStefano Zampini   old_size = -1;
3583e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3584e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3585e7b262bdSStefano Zampini   }
3586e7b262bdSStefano Zampini   if (n_R != old_size) {
3587e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3588e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
35896bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
35906bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
35916bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
35926bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3593e7b262bdSStefano Zampini   }
3594e7b262bdSStefano Zampini   /* local primal dofs */
3595e7b262bdSStefano Zampini   old_size = -1;
3596e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3597e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3598e7b262bdSStefano Zampini   }
3599e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3600e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
360183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3602e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
36036bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3604e7b262bdSStefano Zampini   }
3605e7b262bdSStefano Zampini   /* local explicit constraints */
3606e7b262bdSStefano Zampini   old_size = -1;
3607e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3608e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3609e7b262bdSStefano Zampini   }
3610e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3611e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
361283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
361383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
361483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
361583b7ccabSStefano Zampini   }
36166bfb1811SStefano Zampini   PetscFunctionReturn(0);
36176bfb1811SStefano Zampini }
36186bfb1811SStefano Zampini 
361947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
362088ebb749SStefano Zampini {
362125084f0cSStefano Zampini   PetscErrorCode  ierr;
362225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
362388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
362488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3625d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
362625084f0cSStefano Zampini   /* submatrices of local problem */
362780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
362806656605SStefano Zampini   /* submatrices of local coarse problem */
362906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
363025084f0cSStefano Zampini   /* working matrices */
363106656605SStefano Zampini   Mat             C_CR;
363225084f0cSStefano Zampini   /* additional working stuff */
363306656605SStefano Zampini   PC              pc_R;
3634c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
36355cbda25cSStefano Zampini   Vec             dummy_vec;
3636c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
363725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
363806656605SStefano Zampini   PetscScalar     *work;
363906656605SStefano Zampini   PetscInt        *idx_V_B;
3640ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
364106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3642ffd830a3SStefano Zampini 
364325084f0cSStefano Zampini   /* some shortcuts to scalars */
364406656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
364588ebb749SStefano Zampini 
364688ebb749SStefano Zampini   PetscFunctionBegin;
36479a962809SStefano 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");
3648ffd830a3SStefano Zampini 
3649ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3650b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
36514f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3652b371cd4fSStefano Zampini   n_B = pcis->n_B;
3653b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
365488ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
365588ebb749SStefano Zampini 
365688ebb749SStefano Zampini   /* vertices in boundary numbering */
3657785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
36580e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
36596c4ed002SBarry 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);
366088ebb749SStefano Zampini 
366106656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3662019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
366306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
366406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
366506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
366606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
366706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
366806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
366906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
367006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
367106656605SStefano Zampini 
367206656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
367306656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
367406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
367506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
367606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3677ffd830a3SStefano Zampini   lda_rhs = n_R;
3678a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
367906656605SStefano Zampini   if (isLU || isILU || isCHOL) {
368006656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3681b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3682df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3683d62866d3SStefano Zampini     MatFactorType      type;
3684d62866d3SStefano Zampini 
3685df4d28bfSStefano Zampini     F = reuse_solver->F;
36866816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3687d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3688ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
368922db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
369006656605SStefano Zampini   } else {
369106656605SStefano Zampini     F = NULL;
369206656605SStefano Zampini   }
369306656605SStefano Zampini 
3694c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3695c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3696c58f9fdbSStefano Zampini   if (F) {
3697ea799195SBarry Smith     MatSolverType solver;
3698c58f9fdbSStefano Zampini 
36993ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3700c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3701c58f9fdbSStefano Zampini   }
3702c58f9fdbSStefano Zampini 
3703ffd830a3SStefano Zampini   /* allocate workspace */
3704ffd830a3SStefano Zampini   n = 0;
3705ffd830a3SStefano Zampini   if (n_constraints) {
3706ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3707ffd830a3SStefano Zampini   }
3708ffd830a3SStefano Zampini   if (n_vertices) {
3709ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3710ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3711ffd830a3SStefano Zampini   }
37122a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
37132a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
37142a3a6641Sstefano_zampini   }
3715ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3716ffd830a3SStefano Zampini 
37175cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
37185cbda25cSStefano Zampini   dummy_vec = NULL;
37195cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
37205cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
37215cbda25cSStefano Zampini   }
37225cbda25cSStefano Zampini 
372388ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
372488ebb749SStefano Zampini   if (n_constraints) {
3725837cedc9SStefano Zampini     Mat         M3,C_B;
372606656605SStefano Zampini     IS          is_aux;
372780677318SStefano Zampini     PetscScalar *array,*array2;
372806656605SStefano Zampini 
3729f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
373080677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
373188ebb749SStefano Zampini 
373225084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
373325084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
37347dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
37357dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
373688ebb749SStefano Zampini 
373780677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
373880677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3739c58f9fdbSStefano Zampini     if (!sparserhs) {
3740ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
374188ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
374206656605SStefano Zampini         const PetscScalar *row_cmat_values;
374306656605SStefano Zampini         const PetscInt    *row_cmat_indices;
374406656605SStefano Zampini         PetscInt          size_of_constraint,j;
374588ebb749SStefano Zampini 
374606656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
374706656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3748ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
374906656605SStefano Zampini         }
375006656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
375106656605SStefano Zampini       }
3752c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3753c58f9fdbSStefano Zampini     } else {
3754c58f9fdbSStefano Zampini       Mat tC_CR;
3755c58f9fdbSStefano Zampini 
3756c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3757c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3758c58f9fdbSStefano Zampini         PetscScalar *aa;
3759c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3760c58f9fdbSStefano Zampini         PetscBool   done;
3761c58f9fdbSStefano Zampini 
3762c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
376313903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3764c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3765c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3766c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
376713903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3768c58f9fdbSStefano Zampini       } else {
3769c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3770c58f9fdbSStefano Zampini         tC_CR = C_CR;
3771c58f9fdbSStefano Zampini       }
3772c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3773c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3774c58f9fdbSStefano Zampini     }
3775ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
377606656605SStefano Zampini     if (F) {
3777a3df083aSStefano Zampini       if (need_benign_correction) {
3778df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3779a3df083aSStefano Zampini 
378072b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
378172b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3782a3df083aSStefano Zampini       }
3783c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3784a3df083aSStefano Zampini       if (need_benign_correction) {
3785a3df083aSStefano Zampini         PetscScalar        *marr;
3786df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3787a3df083aSStefano Zampini 
3788a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
37895cbda25cSStefano Zampini         if (lda_rhs != n_R) {
37905cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
37915cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
37925cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
37935cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
37945cbda25cSStefano Zampini           }
37955cbda25cSStefano Zampini         } else {
3796a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3797a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
37985cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3799a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3800a3df083aSStefano Zampini           }
38015cbda25cSStefano Zampini         }
3802a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3803a3df083aSStefano Zampini       }
380406656605SStefano Zampini     } else {
380580677318SStefano Zampini       PetscScalar *marr;
380680677318SStefano Zampini 
380780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
380806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3809ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3810ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
381106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
381206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
381306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
381406656605SStefano Zampini       }
381580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
381606656605SStefano Zampini     }
3817c58f9fdbSStefano Zampini     if (sparserhs) {
3818c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3819c58f9fdbSStefano Zampini     }
3820c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
382180677318SStefano Zampini     if (!pcbddc->switch_static) {
382280677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
382380677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
382480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
382580677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3826ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
382780677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
382880677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
382980677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
383080677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
383180677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
383280677318SStefano Zampini       }
383380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
383480677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
383572b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
383680677318SStefano Zampini     } else {
3837ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3838ffd830a3SStefano Zampini         IS dummy;
3839ffd830a3SStefano Zampini 
3840ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
38417dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3842ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3843ffd830a3SStefano Zampini       } else {
384480677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
384580677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3846ffd830a3SStefano Zampini       }
384725084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
384880677318SStefano Zampini     }
384980677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
385080677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
385180677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
385280677318SStefano Zampini     if (isCHOL) {
385380677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
385480677318SStefano Zampini     } else {
385525084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
385680677318SStefano Zampini     }
3857837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
385880677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
3859837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
386072b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
3861837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
3862837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
3863f4ddd8eeSStefano Zampini   }
3864fc227af8SStefano Zampini 
3865fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
386688ebb749SStefano Zampini   if (n_vertices) {
386706656605SStefano Zampini     IS        is_aux;
3868c58f9fdbSStefano Zampini     PetscBool isseqaij;
38693a50541eSStefano Zampini 
3870b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
38716816873aSStefano Zampini       IS tis;
38726816873aSStefano Zampini 
38736816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
38746816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
38756816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
38766816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
38776816873aSStefano Zampini     } else {
38783a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
38796816873aSStefano Zampini     }
38807dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
38817dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3882c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3883c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
3884c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3885c58f9fdbSStefano Zampini     }
38867dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
388725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
388888ebb749SStefano Zampini   }
388988ebb749SStefano Zampini 
389088ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3891f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
389206656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
389306656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
389406656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
389506656605SStefano Zampini     }
3896f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
389706656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
389806656605SStefano Zampini       PetscScalar *marray;
389906656605SStefano Zampini 
390006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
390106656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3902f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3903f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3904f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3905f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3906f4ddd8eeSStefano Zampini     }
3907f4ddd8eeSStefano Zampini   }
390806656605SStefano Zampini 
3909f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
3910a6e023c1Sstefano_zampini     PetscScalar *marr;
391188ebb749SStefano Zampini 
3912a6e023c1Sstefano_zampini     /* memory size */
391306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
3914a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
3915a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
3916a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
3917a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3918a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
39198eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3920a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3921a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
392288ebb749SStefano Zampini     }
39233301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
3924a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3925a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
39268eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3927a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
392888ebb749SStefano Zampini       }
392988ebb749SStefano Zampini     } else {
3930c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3931c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
39321b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3933c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3934c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3935c0553b1fSStefano Zampini       }
393688ebb749SStefano Zampini     }
393706656605SStefano Zampini   }
3938019a44ceSStefano Zampini 
393906656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
39404f1b2e48SStefano Zampini   p0_lidx_I = NULL;
39414f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3942d12edf2fSStefano Zampini     const PetscInt *idxs;
3943d12edf2fSStefano Zampini 
3944d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
39454f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
39464f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
39474f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
39484f1b2e48SStefano Zampini     }
3949d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3950d12edf2fSStefano Zampini   }
3951d16cbb6bSStefano Zampini 
395206656605SStefano Zampini   /* vertices */
395306656605SStefano Zampini   if (n_vertices) {
3954c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
395516f15bc4SStefano Zampini 
3956af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
395704708bb6SStefano Zampini 
395816f15bc4SStefano Zampini     if (n_R) {
395914393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
396006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
396116f15bc4SStefano Zampini       PetscScalar  *x,*y;
396206656605SStefano Zampini 
396321eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
396414393ed6SStefano Zampini       if (need_benign_correction) {
396514393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
396614393ed6SStefano Zampini         IS                     is_p0;
396714393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
396814393ed6SStefano Zampini 
396914393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
397014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
397114393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3972af25d912SStefano 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);
397314393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
397414393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
39757dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
397614393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
397714393ed6SStefano Zampini       }
397814393ed6SStefano Zampini 
3979c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3980c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
3981ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
3982af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3983ffd830a3SStefano Zampini         } else {
3984ca92afb2SStefano Zampini           PetscScalar    *av,*array;
3985ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
3986ca92afb2SStefano Zampini           PetscInt       n;
3987ca92afb2SStefano Zampini           PetscBool      flg_row;
3988ffd830a3SStefano Zampini 
3989ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
3990ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
39919d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3992ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3993ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3994ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
3995ca92afb2SStefano Zampini             PetscInt j;
3996ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3997ffd830a3SStefano Zampini           }
3998ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3999ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4000ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4001ffd830a3SStefano Zampini         }
4002a3df083aSStefano Zampini         if (need_benign_correction) {
4003df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4004a3df083aSStefano Zampini           PetscScalar        *marr;
4005a3df083aSStefano Zampini 
4006a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
400714393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
400814393ed6SStefano Zampini 
400914393ed6SStefano Zampini                  | 0 0  0 | (V)
401014393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
401114393ed6SStefano Zampini                  | 0 0 -1 | (p0)
401214393ed6SStefano Zampini 
401314393ed6SStefano Zampini           */
4014df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
401514393ed6SStefano Zampini             const PetscScalar *vals;
401614393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
401714393ed6SStefano Zampini             PetscInt          n,j,nz;
401814393ed6SStefano Zampini 
4019df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4020df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
402114393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
402214393ed6SStefano Zampini             for (j=0;j<n;j++) {
402314393ed6SStefano Zampini               PetscScalar val = vals[j];
402414393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
402514393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
402614393ed6SStefano Zampini             }
402714393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4028df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
402914393ed6SStefano Zampini           }
403072b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
403172b8c272SStefano Zampini         }
4032c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4033c58f9fdbSStefano Zampini         Brhs = A_RV;
4034c58f9fdbSStefano Zampini       } else {
4035c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4036c58f9fdbSStefano Zampini 
4037c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4038fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4039c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4040c58f9fdbSStefano Zampini         } else {
4041c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4042c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4043c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4044c58f9fdbSStefano Zampini           A_RVT = A_VR;
4045c58f9fdbSStefano Zampini         }
4046c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4047c58f9fdbSStefano Zampini           PetscScalar *aa;
4048c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4049c58f9fdbSStefano Zampini           PetscBool   done;
4050c58f9fdbSStefano Zampini 
4051c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
405213903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4053c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4054c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4055c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
405613903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4057c58f9fdbSStefano Zampini         } else {
4058c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4059c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4060c58f9fdbSStefano Zampini         }
4061c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4062c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4063c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4064c58f9fdbSStefano Zampini       }
406572b8c272SStefano Zampini       if (F) {
406614393ed6SStefano Zampini         /* need to correct the rhs */
406772b8c272SStefano Zampini         if (need_benign_correction) {
406872b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
406972b8c272SStefano Zampini           PetscScalar        *marr;
407072b8c272SStefano Zampini 
4071c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
40725cbda25cSStefano Zampini           if (lda_rhs != n_R) {
40735cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
40745cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40755cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
40765cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40775cbda25cSStefano Zampini             }
40785cbda25cSStefano Zampini           } else {
4079a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4080a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40815cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4082a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4083a3df083aSStefano Zampini             }
40845cbda25cSStefano Zampini           }
4085c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4086a3df083aSStefano Zampini         }
4087c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4088c58f9fdbSStefano Zampini         if (restoreavr) {
4089c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4090c58f9fdbSStefano Zampini         }
409114393ed6SStefano Zampini         /* need to correct the solution */
4092a3df083aSStefano Zampini         if (need_benign_correction) {
4093df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4094a3df083aSStefano Zampini           PetscScalar        *marr;
4095a3df083aSStefano Zampini 
4096a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
40975cbda25cSStefano Zampini           if (lda_rhs != n_R) {
40985cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
40995cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
41005cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
41015cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
41025cbda25cSStefano Zampini             }
41035cbda25cSStefano Zampini           } else {
4104a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4105a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
41065cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4107a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4108a3df083aSStefano Zampini             }
41095cbda25cSStefano Zampini           }
4110a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4111a3df083aSStefano Zampini         }
411206656605SStefano Zampini       } else {
4113c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
411406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4115ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4116ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
411706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
411806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
411906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
412006656605SStefano Zampini         }
4121c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
412206656605SStefano Zampini       }
412380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4124c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4125ffd830a3SStefano Zampini       /* S_VV and S_CV */
412606656605SStefano Zampini       if (n_constraints) {
412706656605SStefano Zampini         Mat B;
412880677318SStefano Zampini 
4129ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
413080677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4131ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4132ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
413380677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
413480677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
413580677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
413680677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
413780677318SStefano Zampini         }
4138ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
413980677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
414080677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4141ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
414280677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
414306656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4144ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4145ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
414606656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
414706656605SStefano Zampini       }
4148ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4149ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4150ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4151ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4152ffd830a3SStefano Zampini       }
415306656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
415414393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
415514393ed6SStefano Zampini       if (need_benign_correction) {
4156df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
415714393ed6SStefano Zampini         PetscScalar      *marr,*sums;
415814393ed6SStefano Zampini 
415914393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4160f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4161df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
416214393ed6SStefano Zampini           const PetscScalar *vals;
416314393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
416414393ed6SStefano Zampini           PetscInt          n,j,nz;
416514393ed6SStefano Zampini 
4166df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4167df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
416814393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
416914393ed6SStefano Zampini             PetscInt k;
417014393ed6SStefano Zampini             sums[j] = 0.;
417114393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
417214393ed6SStefano Zampini           }
417314393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
417414393ed6SStefano Zampini           for (j=0;j<n;j++) {
417514393ed6SStefano Zampini             PetscScalar val = vals[j];
417614393ed6SStefano Zampini             PetscInt k;
417714393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
417814393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
417914393ed6SStefano Zampini             }
418014393ed6SStefano Zampini           }
418114393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4182df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
418314393ed6SStefano Zampini         }
418414393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4185f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
418614393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
418714393ed6SStefano Zampini       }
418880677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
418906656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
419006656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
419106656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
419206656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
419306656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
419406656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
419506656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4196d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4197019a44ceSStefano Zampini     } else {
4198d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4199d16cbb6bSStefano Zampini     }
420021eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4201d16cbb6bSStefano Zampini 
420206656605SStefano Zampini     /* coarse basis functions */
420306656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
420416f15bc4SStefano Zampini       PetscScalar *y;
420516f15bc4SStefano Zampini 
4206ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
420706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
420806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
420906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
421006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
421106656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
421206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
421306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
421406656605SStefano Zampini 
421506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
42164f1b2e48SStefano Zampini         PetscInt j;
42174f1b2e48SStefano Zampini 
421806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
421906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
422006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
422106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
422206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
42234f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
422406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
422506656605SStefano Zampini       }
422606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
422706656605SStefano Zampini     }
422804708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
422904708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
423006656605SStefano Zampini   }
42315cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
423206656605SStefano Zampini 
423306656605SStefano Zampini   if (n_constraints) {
423406656605SStefano Zampini     Mat B;
423506656605SStefano Zampini 
4236ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
423706656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
423880677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
423906656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
424006656605SStefano Zampini     if (n_vertices) {
424103dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
424280677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
424380677318SStefano Zampini       } else {
424480677318SStefano Zampini         Mat S_VCt;
424580677318SStefano Zampini 
4246ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4247ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
424872b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4249ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4250ffd830a3SStefano Zampini         }
425180677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
425280677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
425380677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
425480677318SStefano Zampini       }
425506656605SStefano Zampini     }
425606656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
425706656605SStefano Zampini     /* coarse basis functions */
425806656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
425906656605SStefano Zampini       PetscScalar *y;
426006656605SStefano Zampini 
4261ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
426206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
426306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
426406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
426506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
426606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
426706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
426806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
42694f1b2e48SStefano Zampini         PetscInt j;
42704f1b2e48SStefano Zampini 
427106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
427206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
427306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
42764f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
427706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
427806656605SStefano Zampini       }
427906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
428006656605SStefano Zampini     }
428106656605SStefano Zampini   }
428280677318SStefano Zampini   if (n_constraints) {
428380677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
428480677318SStefano Zampini   }
42854f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
428672b8c272SStefano Zampini 
428772b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
428872b8c272SStefano Zampini   if (pcbddc->benign_n) {
428972b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
429072b8c272SStefano Zampini     IS          is_dummy;
429172b8c272SStefano Zampini     PetscScalar *data;
429272b8c272SStefano Zampini     PetscInt    j;
429372b8c272SStefano Zampini 
429472b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
42957dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
429672b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
429772b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
429886c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
429972b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
430072b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
430172b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
430272b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
430372b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
430472b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
430572b8c272SStefano Zampini       }
430672b8c272SStefano Zampini     }
430772b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
430872b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
430972b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
431072b8c272SStefano Zampini   }
4311019a44ceSStefano Zampini 
431206656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
43133301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4314ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4315ffd830a3SStefano Zampini     PetscScalar *marray;
431606656605SStefano Zampini 
431706656605SStefano Zampini     if (n_constraints) {
4318ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
431906656605SStefano Zampini 
4320abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
432106656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4322ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
432316f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
432406656605SStefano Zampini       if (n_vertices) {
4325ffd830a3SStefano Zampini         Mat S_VCT;
432606656605SStefano Zampini 
432706656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4328ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
432916f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
433006656605SStefano Zampini       }
4331ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
43325b782168SStefano Zampini     } else {
43335b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
433406656605SStefano Zampini     }
433516f15bc4SStefano Zampini     if (n_vertices && n_R) {
4336ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4337ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4338ffd830a3SStefano Zampini       PetscInt       n;
4339ffd830a3SStefano Zampini       PetscBool      flg_row;
434006656605SStefano Zampini 
4341ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4342af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4343ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4344ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4345ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4346ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4347ffd830a3SStefano Zampini         PetscInt j;
4348ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4349ffd830a3SStefano Zampini       }
4350ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4351ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4352ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
435306656605SStefano Zampini     }
435406656605SStefano Zampini 
4355ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4356abc8f43dSstefano_zampini     if (n_vertices) {
4357ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4358ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4359ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4360ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
436106656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
436206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
436306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
436406656605SStefano Zampini       }
4365ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4366abc8f43dSstefano_zampini     }
43675b782168SStefano Zampini     if (B_C) {
4368ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4369ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4370ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4371ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4372ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4373ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4374ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
437506656605SStefano Zampini       }
4376ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
43775b782168SStefano Zampini     }
437806656605SStefano Zampini     /* coarse basis functions */
437906656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
438006656605SStefano Zampini       PetscScalar *y;
438106656605SStefano Zampini 
4382ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
438306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
438406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);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       if (i<n_vertices) {
438806656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
438906656605SStefano Zampini       }
439006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
439106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
439206656605SStefano Zampini 
439306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
439406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
439506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
439606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
439706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
439806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
439906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
440006656605SStefano Zampini       }
440106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
440206656605SStefano Zampini     }
4403ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4404ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
440506656605SStefano Zampini   }
4406a6e023c1Sstefano_zampini 
4407d62866d3SStefano Zampini   /* free memory */
440888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
440906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
441006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
441106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
441206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4413d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4414d62866d3SStefano Zampini   if (n_vertices) {
4415d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4416d62866d3SStefano Zampini   }
4417d62866d3SStefano Zampini   if (n_constraints) {
4418d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4419d62866d3SStefano Zampini   }
442088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
442188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
442288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4423d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
442488ebb749SStefano Zampini     Mat         coarse_sub_mat;
442525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
442688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
442788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
442888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
44298bec7fa6SStefano Zampini     Mat         C_B,CPHI;
44308bec7fa6SStefano Zampini     IS          is_dummy;
44318bec7fa6SStefano Zampini     Vec         mones;
443288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
443388ebb749SStefano Zampini     PetscReal   real_value;
443488ebb749SStefano Zampini 
4435a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4436a3df083aSStefano Zampini       Mat A;
4437a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
44387dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
44397dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
44407dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
44417dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4442a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4443a3df083aSStefano Zampini     } else {
444488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
444588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
444688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
444788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4448a3df083aSStefano Zampini     }
444988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
445088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4451ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
445288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
445388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
445488ebb749SStefano Zampini     }
445588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
445688ebb749SStefano Zampini 
445725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
44583301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
445925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4460ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
446188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
446288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
446388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
446488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
446588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
446688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
446788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
446888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
446988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
447088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
447188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
447288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
447388ebb749SStefano Zampini     } else {
447488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
447588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
447688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
447788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
447888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
447988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
448088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
448188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
448288ebb749SStefano Zampini     }
448388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
448488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
448588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4486511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
44874f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4488fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4489d12edf2fSStefano Zampini       PetscScalar *data,*data2;
44904f1b2e48SStefano Zampini       PetscInt    j;
4491d12edf2fSStefano Zampini 
44924f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44937dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4494d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
449586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4496d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4497d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
44984f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
44994f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4500d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
45014f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
45024f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
45034f1b2e48SStefano Zampini         }
4504d12edf2fSStefano Zampini       }
4505d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4506d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4507d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4508d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4509d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4510d12edf2fSStefano Zampini     }
4511d12edf2fSStefano Zampini #if 0
4512d12edf2fSStefano Zampini   {
4513d12edf2fSStefano Zampini     PetscViewer viewer;
4514d12edf2fSStefano Zampini     char filename[256];
4515ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4516d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4517a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4518ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4519ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4520ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4521d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4522a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4523ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4524ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
452572b8c272SStefano Zampini     }
4526ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4527ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4528ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4529ffd830a3SStefano Zampini     }
4530ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4531ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4532ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4533ffd830a3SStefano Zampini     }
453472b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4535ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4536ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4537ffd830a3SStefano Zampini     }
4538fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4539fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4540fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4541fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4542fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4543fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4544fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4545fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4546fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4547fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4548d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4549d12edf2fSStefano Zampini   }
4550d12edf2fSStefano Zampini #endif
455181d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
45528bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
45531575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
455406656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
45558bec7fa6SStefano Zampini 
45568bec7fa6SStefano Zampini     /* check constraints */
4557a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
45587dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
45594f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
45608bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4561a00504b5SStefano Zampini     } else {
4562a00504b5SStefano Zampini       PetscScalar *data;
4563a00504b5SStefano Zampini       Mat         tmat;
4564a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4565a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4566a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4567a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4568a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4569a00504b5SStefano Zampini     }
45708bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
45718bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
45728bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
45738bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4574bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4575ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4576bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4577bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4578bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4579bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4580bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
458188ebb749SStefano Zampini     }
45828bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
45838bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
45848bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
45858bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
458625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
458788ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
458888ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
458988ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
459088ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
459188ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
459288ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
459388ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
459488ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
459588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
459688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4597ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
459888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
459988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
460088ebb749SStefano Zampini     }
460188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
460288ebb749SStefano Zampini   }
46038629588bSStefano Zampini   /* get back data */
46048629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
460588ebb749SStefano Zampini   PetscFunctionReturn(0);
460688ebb749SStefano Zampini }
460788ebb749SStefano Zampini 
46087dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4609aa0d41d4SStefano Zampini {
4610d65f70fdSStefano Zampini   Mat            *work_mat;
4611d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4612d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4613c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4614aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4615aa0d41d4SStefano Zampini 
4616aa0d41d4SStefano Zampini   PetscFunctionBegin;
4617d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4618d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4619d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4620d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4621aa0d41d4SStefano Zampini 
4622d65f70fdSStefano Zampini   if (!rsorted) {
4623906d46d4SStefano Zampini     const PetscInt *idxs;
4624906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4625aa0d41d4SStefano Zampini 
4626d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4627d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4628d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4629d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4630aa0d41d4SStefano Zampini     }
4631d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4632d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4633d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4634d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4635aa0d41d4SStefano Zampini     }
4636d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4637d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4638d65f70fdSStefano Zampini   } else {
4639d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4640d65f70fdSStefano Zampini     isrow_s = isrow;
4641aa0d41d4SStefano Zampini   }
4642906d46d4SStefano Zampini 
4643d65f70fdSStefano Zampini   if (!csorted) {
4644d65f70fdSStefano Zampini     if (isrow == iscol) {
4645d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4646d65f70fdSStefano Zampini       iscol_s = isrow_s;
4647d65f70fdSStefano Zampini     } else {
4648d65f70fdSStefano Zampini       const PetscInt *idxs;
4649d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4650906d46d4SStefano Zampini 
4651d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4652d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4653d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4654d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4655d65f70fdSStefano Zampini       }
4656d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4657d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4658d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4659d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4660d65f70fdSStefano Zampini       }
4661d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4662d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4663d65f70fdSStefano Zampini     }
4664d65f70fdSStefano Zampini   } else {
4665d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4666d65f70fdSStefano Zampini     iscol_s = iscol;
4667d65f70fdSStefano Zampini   }
4668d65f70fdSStefano Zampini 
46697dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4670d65f70fdSStefano Zampini 
4671d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4672906d46d4SStefano Zampini     Mat      new_mat;
4673d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4674906d46d4SStefano Zampini 
4675d65f70fdSStefano Zampini     if (!rsorted) {
4676d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4677d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4678d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4679d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4680906d46d4SStefano Zampini       }
4681d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4682d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4683d65f70fdSStefano Zampini     } else {
4684d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4685906d46d4SStefano Zampini     }
4686d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4687d65f70fdSStefano Zampini 
4688d65f70fdSStefano Zampini     if (!csorted) {
4689d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4690d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4691d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4692d65f70fdSStefano Zampini       } else {
4693d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4694f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4695d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4696d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4697d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4698d65f70fdSStefano Zampini         }
4699d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4700d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4701d65f70fdSStefano Zampini       }
4702d65f70fdSStefano Zampini     } else {
4703d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4704d65f70fdSStefano Zampini     }
4705d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4706d65f70fdSStefano Zampini 
4707d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4708d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4709d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4710d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4711d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4712d65f70fdSStefano Zampini   }
4713d65f70fdSStefano Zampini 
4714d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4715d65f70fdSStefano Zampini   *B = work_mat[0];
4716d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4717d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4718d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4719d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4720d65f70fdSStefano Zampini }
4721d65f70fdSStefano Zampini 
47225e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4723aa0d41d4SStefano Zampini {
4724aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
47255e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4726022d8d2bSstefano_zampini   Mat            new_mat,lA;
47275e8657edSStefano Zampini   IS             is_local,is_global;
4728d65f70fdSStefano Zampini   PetscInt       local_size;
4729d65f70fdSStefano Zampini   PetscBool      isseqaij;
4730aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4731aa0d41d4SStefano Zampini 
4732aa0d41d4SStefano Zampini   PetscFunctionBegin;
4733aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
47345e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
47355e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4736b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4737aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
47387dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4739aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4740906d46d4SStefano Zampini 
4741906d46d4SStefano Zampini   /* check */
4742906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4743906d46d4SStefano Zampini     Vec       x,x_change;
4744906d46d4SStefano Zampini     PetscReal error;
4745906d46d4SStefano Zampini 
47465e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4747906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
47485e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4749e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4750e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4751d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
475288428137SStefano Zampini     if (!pcbddc->change_interior) {
475388428137SStefano Zampini       const PetscScalar *x,*y,*v;
475488428137SStefano Zampini       PetscReal         lerror = 0.;
475588428137SStefano Zampini       PetscInt          i;
475688428137SStefano Zampini 
475788428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
475888428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
475988428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
476088428137SStefano Zampini       for (i=0;i<local_size;i++)
476188428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
476288428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
476388428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
476488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
476588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
476688428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4767637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4768637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4769637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4770637e8532SStefano Zampini         } else {
4771637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4772637e8532SStefano Zampini         }
4773637e8532SStefano Zampini       }
477488428137SStefano Zampini     }
4775e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4776e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4777906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4778906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4779637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4780637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4781637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4782637e8532SStefano Zampini       } else {
4783637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4784637e8532SStefano Zampini       }
4785637e8532SStefano Zampini     }
4786906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4787906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4788906d46d4SStefano Zampini   }
4789906d46d4SStefano Zampini 
4790022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4791022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4792022d8d2bSstefano_zampini 
479322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
47949b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
479522d5777bSStefano Zampini   if (isseqaij) {
4796a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4797a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4798022d8d2bSstefano_zampini     if (lA) {
4799022d8d2bSstefano_zampini       Mat work;
4800022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4801022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4802022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4803022d8d2bSstefano_zampini     }
4804aa0d41d4SStefano Zampini   } else {
4805a00504b5SStefano Zampini     Mat work_mat;
48061cf9b237SStefano Zampini 
4807a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4808aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4809a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
48101d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4811022d8d2bSstefano_zampini     if (lA) {
4812022d8d2bSstefano_zampini       Mat work;
4813022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4814022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4815022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4816022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4817022d8d2bSstefano_zampini     }
4818aa0d41d4SStefano Zampini   }
48193301b35fSStefano Zampini   if (matis->A->symmetric_set) {
48203301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4821e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
48223301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4823e496cd5dSStefano Zampini #endif
48243301b35fSStefano Zampini   }
4825d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4826aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4827aa0d41d4SStefano Zampini }
4828aa0d41d4SStefano Zampini 
48298ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4830a64d13efSStefano Zampini {
4831a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4832a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4833d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
483453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
48353a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
48363a50541eSStefano Zampini   PetscInt        vbs,bs;
48376816873aSStefano Zampini   PetscBT         bitmask=NULL;
4838a64d13efSStefano Zampini   PetscErrorCode  ierr;
4839a64d13efSStefano Zampini 
4840a64d13efSStefano Zampini   PetscFunctionBegin;
4841b23d619eSStefano Zampini   /*
4842b23d619eSStefano Zampini     No need to setup local scatters if
4843b23d619eSStefano Zampini       - primal space is unchanged
4844b23d619eSStefano Zampini         AND
4845b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4846b23d619eSStefano Zampini         AND
4847b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4848b23d619eSStefano Zampini   */
4849b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4850f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4851f4ddd8eeSStefano Zampini   }
4852f4ddd8eeSStefano Zampini   /* destroy old objects */
4853f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4854f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4855f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4856a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4857b371cd4fSStefano Zampini   n_B = pcis->n_B;
4858b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4859b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
48603a50541eSStefano Zampini 
4861a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
48626816873aSStefano Zampini 
486353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4864b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4865854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4866a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4867a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
48680e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4869a64d13efSStefano Zampini     }
4870a64d13efSStefano Zampini 
4871a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
48724641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
48736816873aSStefano Zampini         idx_R_local[n_R++] = i;
4874a64d13efSStefano Zampini       }
4875a64d13efSStefano Zampini     }
4876df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4877df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
48786816873aSStefano Zampini 
4879df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4880df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
48816816873aSStefano Zampini   }
48823a50541eSStefano Zampini 
48833a50541eSStefano Zampini   /* Block code */
48843a50541eSStefano Zampini   vbs = 1;
48853a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
48863a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
48873a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
48883a50541eSStefano Zampini     PetscInt  *vary;
4889b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4890785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
48913a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4892d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4893d3df7717SStefano 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 */
48940e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4895d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
48963a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
48973a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
48983a50541eSStefano Zampini           break;
48993a50541eSStefano Zampini         }
49003a50541eSStefano Zampini       }
4901d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4902d3df7717SStefano Zampini     } else {
4903d3df7717SStefano Zampini       /* Verify directly the R set */
4904d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4905d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4906d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4907d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4908d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4909d3df7717SStefano Zampini             break;
4910d3df7717SStefano Zampini           }
4911d3df7717SStefano Zampini         }
4912d3df7717SStefano Zampini       }
4913d3df7717SStefano Zampini     }
49143a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
49153a50541eSStefano Zampini       vbs = bs;
49163a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
49173a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
49183a50541eSStefano Zampini       }
49193a50541eSStefano Zampini     }
49203a50541eSStefano Zampini   }
49213a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4922b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4923df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
492453892102SStefano Zampini 
4925df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4926df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
492753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4928df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
492953892102SStefano Zampini   } else {
49303a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
493153892102SStefano Zampini   }
4932a64d13efSStefano Zampini 
4933a64d13efSStefano Zampini   /* print some info if requested */
4934a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4935a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4936a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
49371575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4938a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4939a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
49404f1b2e48SStefano 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);
4941a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4942a64d13efSStefano Zampini   }
4943a64d13efSStefano Zampini 
4944a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4945b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
49466816873aSStefano Zampini     IS       is_aux1,is_aux2;
49476816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
49486816873aSStefano Zampini 
49493a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4950854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4951854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4952a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
49534641a718SStefano Zampini     for (i=0; i<n_D; i++) {
49544641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
49554641a718SStefano Zampini     }
4956a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4957a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
49584641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
49594641a718SStefano Zampini         aux_array1[j++] = i;
4960a64d13efSStefano Zampini       }
4961a64d13efSStefano Zampini     }
4962a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4963a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4964a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
49654641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
49664641a718SStefano Zampini         aux_array2[j++] = i;
4967a64d13efSStefano Zampini       }
4968a64d13efSStefano Zampini     }
4969a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4970a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4971a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4972a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4973a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4974a64d13efSStefano Zampini 
49758eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4976785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4977a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
49784641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
49794641a718SStefano Zampini           aux_array1[j++] = i;
4980a64d13efSStefano Zampini         }
4981a64d13efSStefano Zampini       }
4982a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4983a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4984a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4985a64d13efSStefano Zampini     }
49864641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
49873a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4988d62866d3SStefano Zampini   } else {
4989df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
49906816873aSStefano Zampini     IS                 tis;
49916816873aSStefano Zampini     PetscInt           schur_size;
49926816873aSStefano Zampini 
4993df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
49946816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4995df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
49966816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
49976816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
49986816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
49996816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
50006816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5001d62866d3SStefano Zampini     }
5002d62866d3SStefano Zampini   }
5003a64d13efSStefano Zampini   PetscFunctionReturn(0);
5004a64d13efSStefano Zampini }
5005a64d13efSStefano Zampini 
5006304d26faSStefano Zampini 
5007684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5008304d26faSStefano Zampini {
5009304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5010304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5011304d26faSStefano Zampini   PC             pc_temp;
5012304d26faSStefano Zampini   Mat            A_RR;
5013f4ddd8eeSStefano Zampini   MatReuse       reuse;
5014304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5015304d26faSStefano Zampini   PetscReal      value;
501604708bb6SStefano Zampini   PetscInt       n_D,n_R;
501735529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
5018304d26faSStefano Zampini   PetscErrorCode ierr;
5019e604994aSStefano Zampini   /* prefixes stuff */
5020312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5021e604994aSStefano Zampini   size_t         len;
5022304d26faSStefano Zampini 
5023304d26faSStefano Zampini   PetscFunctionBegin;
5024304d26faSStefano Zampini 
5025e604994aSStefano Zampini   /* compute prefixes */
5026e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5027e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5028e604994aSStefano Zampini   if (!pcbddc->current_level) {
5029e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5030e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5031e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
5032e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
5033e604994aSStefano Zampini   } else {
503435529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5035e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5036e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5037312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5038312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
503934d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
504034d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5041e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
5042e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
5043e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
5044e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
5045e604994aSStefano Zampini   }
5046e604994aSStefano Zampini 
5047304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5048684f6988SStefano Zampini   if (dirichlet) {
5049d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5050450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
50519a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
5052450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5053a3df083aSStefano Zampini         Mat    A_IIn;
5054a3df083aSStefano Zampini 
5055a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5056a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5057a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5058a3df083aSStefano Zampini       }
5059450f8f5eSStefano Zampini     }
50603301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
50613301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
5062964fefecSStefano Zampini     }
5063ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5064964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
5065304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
5066*cd18cfedSStefano Zampini       void (*f)(void) = 0;
5067*cd18cfedSStefano Zampini 
5068304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5069304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5070304d26faSStefano Zampini       /* default */
5071304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5072e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
50739577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5074304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
50759577ea80SStefano Zampini       if (issbaij) {
50769577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
50779577ea80SStefano Zampini       } else {
5078304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
50799577ea80SStefano Zampini       }
5080304d26faSStefano Zampini       /* Allow user's customization */
5081304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5082*cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5083*cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5084*cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5085*cd18cfedSStefano Zampini         const PetscInt *idxs;
5086*cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5087*cd18cfedSStefano Zampini 
5088*cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5089*cd18cfedSStefano Zampini         ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5090*cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5091*cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5092*cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5093*cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5094*cd18cfedSStefano Zampini           }
5095*cd18cfedSStefano Zampini         }
5096*cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5097*cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5098*cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5099*cd18cfedSStefano Zampini       }
5100304d26faSStefano Zampini     }
5101d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5102b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5103df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5104d62866d3SStefano Zampini 
5105df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5106d5574798SStefano Zampini     }
5107304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5108304d26faSStefano Zampini     if (!n_D) {
5109304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5110304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5111304d26faSStefano Zampini     }
5112304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
5113304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
5114304d26faSStefano Zampini     /* set ksp_D into pcis data */
5115304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5116304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5117304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5118684f6988SStefano Zampini   }
5119304d26faSStefano Zampini 
5120304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5121684f6988SStefano Zampini   A_RR = 0;
5122684f6988SStefano Zampini   if (neumann) {
5123d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
512404708bb6SStefano Zampini     PetscInt        ibs,mbs;
51250aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
512604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
51270aa714b2SStefano Zampini 
51280aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
51290aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
51300aa714b2SStefano Zampini       IS iP;
51310aa714b2SStefano Zampini 
51320aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
51330aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
51340aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
51350aa714b2SStefano Zampini     }
5136f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
51378ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5138f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5139f4ddd8eeSStefano Zampini       PetscInt nn_R;
514081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5141f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5142f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5143f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5144f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5145f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5146f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5147f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5148727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5149f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5150f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5151f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5152f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5153f4ddd8eeSStefano Zampini         }
5154f4ddd8eeSStefano Zampini       }
5155f4ddd8eeSStefano Zampini       /* last check */
5156d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5157f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5158f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5159f4ddd8eeSStefano Zampini       }
5160f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5161f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5162f4ddd8eeSStefano Zampini     }
5163a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5164af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5165af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
516604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
516704708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
516804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
516904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
517004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5171af732b37SStefano Zampini       } else {
5172511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
51736816873aSStefano Zampini       }
517404708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
517504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
517604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
517704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
517804708bb6SStefano Zampini       } else {
5179511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
518004708bb6SStefano Zampini       }
518104708bb6SStefano Zampini     }
5182a00504b5SStefano Zampini     /* extract A_RR */
51830aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5184a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5185a00504b5SStefano Zampini 
5186a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
518716e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5188a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
518916e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
519016e386b8SStefano Zampini         } else {
51917dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5192a00504b5SStefano Zampini         }
5193a00504b5SStefano Zampini       } else {
5194a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5195a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5196a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5197a00504b5SStefano Zampini       }
5198a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
51997dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
520016e386b8SStefano Zampini     }
52013301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
52023301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
52036816873aSStefano Zampini     }
5204f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5205*cd18cfedSStefano Zampini       void (*f)(void) = 0;
5206*cd18cfedSStefano Zampini 
5207304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5208304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5209304d26faSStefano Zampini       /* default */
5210304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5211e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5212304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
52139577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
52149577ea80SStefano Zampini       if (issbaij) {
52159577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
52169577ea80SStefano Zampini       } else {
5217304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
52189577ea80SStefano Zampini       }
5219304d26faSStefano Zampini       /* Allow user's customization */
5220304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5221*cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5222*cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5223*cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5224*cd18cfedSStefano Zampini         const PetscInt *idxs;
5225*cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5226*cd18cfedSStefano Zampini 
5227*cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5228*cd18cfedSStefano Zampini         ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5229*cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5230*cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5231*cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5232*cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5233*cd18cfedSStefano Zampini           }
5234*cd18cfedSStefano Zampini         }
5235*cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5236*cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5237*cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5238*cd18cfedSStefano Zampini       }
5239304d26faSStefano Zampini     }
5240304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5241304d26faSStefano Zampini     if (!n_R) {
5242304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5243304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5244304d26faSStefano Zampini     }
52455cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5246df4d28bfSStefano Zampini     /* Reuse solver if it is present */
52470aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5248df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5249d62866d3SStefano Zampini 
5250df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5251d62866d3SStefano Zampini     }
5252304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
5253304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
5254684f6988SStefano Zampini   }
5255304d26faSStefano Zampini 
5256684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5257684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
52581575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5259684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5260684f6988SStefano Zampini   }
5261c7017625SStefano Zampini 
5262c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
526335529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5264c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5265c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5266c7017625SStefano Zampini   }
5267c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
526835529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5269c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5270c7017625SStefano Zampini   }
5271c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
527235529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5273c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5274c7017625SStefano Zampini   }
5275c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5276c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5277684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
52780fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
52790fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
52800fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
52810fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
52820fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5283e604994aSStefano 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);
528435529e7bSStefano Zampini       if (check_corr) {
5285c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5286c7017625SStefano Zampini       }
5287304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5288304d26faSStefano Zampini     }
5289684f6988SStefano Zampini     if (neumann) { /* Neumann */
52900fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
52910fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
52920fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
52930fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
52940fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5295e604994aSStefano 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);
529635529e7bSStefano Zampini       if (check_corr) {
5297c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5298c7017625SStefano Zampini       }
5299304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5300304d26faSStefano Zampini     }
5301684f6988SStefano Zampini   }
53025cbda25cSStefano Zampini   /* free Neumann problem's matrix */
53035cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5304304d26faSStefano Zampini   PetscFunctionReturn(0);
5305304d26faSStefano Zampini }
5306304d26faSStefano Zampini 
530780677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5308674ae819SStefano Zampini {
5309674ae819SStefano Zampini   PetscErrorCode  ierr;
5310674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5311be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5312b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5313674ae819SStefano Zampini 
5314674ae819SStefano Zampini   PetscFunctionBegin;
5315b334f244SStefano Zampini   if (!reuse_solver) {
531680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
531720c7b377SStefano Zampini   }
531880677318SStefano Zampini   if (!pcbddc->switch_static) {
531980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
532080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
532180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
532220c7b377SStefano Zampini     }
5323b334f244SStefano Zampini     if (!reuse_solver) {
532480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
532580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
532620c7b377SStefano Zampini     } else {
5327df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5328be83ff47SStefano Zampini 
5329df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5330df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
533120c7b377SStefano Zampini     }
5332be83ff47SStefano Zampini   } else {
533380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
533480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
533580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
533680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
533780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
533880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
533980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
534080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
534180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5342674ae819SStefano Zampini     }
5343674ae819SStefano Zampini   }
5344b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
534580677318SStefano Zampini     if (applytranspose) {
534680677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
534780677318SStefano Zampini     } else {
534880677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
534980677318SStefano Zampini     }
5350be83ff47SStefano Zampini   } else {
5351df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5352be83ff47SStefano Zampini 
5353be83ff47SStefano Zampini     if (applytranspose) {
5354df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5355be83ff47SStefano Zampini     } else {
5356df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5357be83ff47SStefano Zampini     }
5358be83ff47SStefano Zampini   }
535980677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
536080677318SStefano Zampini   if (!pcbddc->switch_static) {
5361b334f244SStefano Zampini     if (!reuse_solver) {
536280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
536380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5364be83ff47SStefano Zampini     } else {
5365df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5366be83ff47SStefano Zampini 
5367df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5368df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5369be83ff47SStefano Zampini     }
537080677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
537180677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
537280677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
537380677318SStefano Zampini     }
537480677318SStefano Zampini   } else {
537580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
538080677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
538180677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
538280677318SStefano Zampini     }
538380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
538480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
538580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
538680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5387674ae819SStefano Zampini   }
5388674ae819SStefano Zampini   PetscFunctionReturn(0);
5389674ae819SStefano Zampini }
5390674ae819SStefano Zampini 
5391dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5392dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5393674ae819SStefano Zampini {
5394674ae819SStefano Zampini   PetscErrorCode ierr;
5395674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5396674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5397674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5398674ae819SStefano Zampini 
5399674ae819SStefano Zampini   PetscFunctionBegin;
5400dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
54014fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5402dc359a40SStefano Zampini     if (applytranspose) {
5403674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
54048eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5405dc359a40SStefano Zampini     } else {
5406674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5407674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
540815aaf578SStefano Zampini     }
54094fee134fSStefano Zampini   } else {
54104fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
54114fee134fSStefano Zampini   }
5412efc2fbd9SStefano Zampini 
5413efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
54144f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5415efc2fbd9SStefano Zampini     PetscScalar *array;
54164f1b2e48SStefano Zampini     PetscInt    j;
5417efc2fbd9SStefano Zampini 
5418efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
54194f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5420efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5421efc2fbd9SStefano Zampini   }
5422efc2fbd9SStefano Zampini 
542312edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
542412edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
542512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
542612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
542712edc857SStefano Zampini 
54289f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
542912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
543051694757SStefano Zampini     Mat          coarse_mat;
5431964fefecSStefano Zampini     Vec          rhs,sol;
543251694757SStefano Zampini     MatNullSpace nullsp;
543327b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5434964fefecSStefano Zampini 
543527b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
543627b6a85dSStefano Zampini       PC        coarse_pc;
543727b6a85dSStefano Zampini 
543827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
543927b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
544027b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
544127b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
544227b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
544327b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
54443bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
544527b6a85dSStefano Zampini       }
544627b6a85dSStefano Zampini     }
5447964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5448964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
544951694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
545051694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
545151694757SStefano Zampini     if (nullsp) {
545251694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
545351694757SStefano Zampini     }
545412edc857SStefano Zampini     if (applytranspose) {
54559a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5456964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
54572701bc32SStefano Zampini     } else {
54581f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
54592701bc32SStefano Zampini         PC        coarse_pc;
54602701bc32SStefano Zampini 
54612701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
54622701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
54633e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
54642701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
546512edc857SStefano Zampini       } else {
5466964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
546712edc857SStefano Zampini       }
54682701bc32SStefano Zampini     }
54691d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
547027b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
547127b6a85dSStefano Zampini       PC        coarse_pc;
547227b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
547327b6a85dSStefano Zampini 
547427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
547527b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
547627b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
54773bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
547827b6a85dSStefano Zampini     }
547951694757SStefano Zampini     if (nullsp) {
548051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
548151694757SStefano Zampini     }
548212edc857SStefano Zampini   }
5483674ae819SStefano Zampini 
5484674ae819SStefano Zampini   /* Local solution on R nodes */
54854fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
548680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
54879f00e9b4SStefano Zampini   }
54889f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
54899f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
549012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5491674ae819SStefano Zampini 
54924fee134fSStefano Zampini   /* Sum contributions from the two levels */
54934fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5494dc359a40SStefano Zampini     if (applytranspose) {
5495dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5496dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5497dc359a40SStefano Zampini     } else {
5498674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
54998eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5500dc359a40SStefano Zampini     }
5501efc2fbd9SStefano Zampini     /* store p0 */
55024f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5503efc2fbd9SStefano Zampini       PetscScalar *array;
55044f1b2e48SStefano Zampini       PetscInt    j;
5505efc2fbd9SStefano Zampini 
5506efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
55074f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5508efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5509efc2fbd9SStefano Zampini     }
55104fee134fSStefano Zampini   } else { /* expand the coarse solution */
55114fee134fSStefano Zampini     if (applytranspose) {
55124fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
55134fee134fSStefano Zampini     } else {
55144fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
55154fee134fSStefano Zampini     }
55164fee134fSStefano Zampini   }
5517674ae819SStefano Zampini   PetscFunctionReturn(0);
5518674ae819SStefano Zampini }
5519674ae819SStefano Zampini 
552012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5521674ae819SStefano Zampini {
5522674ae819SStefano Zampini   PetscErrorCode ierr;
5523674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
552458da7f69SStefano Zampini   PetscScalar    *array;
552512edc857SStefano Zampini   Vec            from,to;
5526674ae819SStefano Zampini 
5527674ae819SStefano Zampini   PetscFunctionBegin;
552812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
552912edc857SStefano Zampini     from = pcbddc->coarse_vec;
553012edc857SStefano Zampini     to = pcbddc->vec1_P;
553112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
553212edc857SStefano Zampini       Vec tvec;
553358da7f69SStefano Zampini 
553458da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
553558da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
553612edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
553758da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
553858da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
553958da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
554012edc857SStefano Zampini     }
554112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
554212edc857SStefano Zampini     from = pcbddc->vec1_P;
554312edc857SStefano Zampini     to = pcbddc->coarse_vec;
554412edc857SStefano Zampini   }
554512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5546674ae819SStefano Zampini   PetscFunctionReturn(0);
5547674ae819SStefano Zampini }
5548674ae819SStefano Zampini 
554912edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5550674ae819SStefano Zampini {
5551674ae819SStefano Zampini   PetscErrorCode ierr;
5552674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
555358da7f69SStefano Zampini   PetscScalar    *array;
555412edc857SStefano Zampini   Vec            from,to;
5555674ae819SStefano Zampini 
5556674ae819SStefano Zampini   PetscFunctionBegin;
555712edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
555812edc857SStefano Zampini     from = pcbddc->coarse_vec;
555912edc857SStefano Zampini     to = pcbddc->vec1_P;
556012edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
556112edc857SStefano Zampini     from = pcbddc->vec1_P;
556212edc857SStefano Zampini     to = pcbddc->coarse_vec;
556312edc857SStefano Zampini   }
556412edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
556512edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
556612edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
556712edc857SStefano Zampini       Vec tvec;
556858da7f69SStefano Zampini 
556912edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
557058da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
557158da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
557258da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
557358da7f69SStefano Zampini     }
557458da7f69SStefano Zampini   } else {
557558da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
557658da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
557712edc857SStefano Zampini     }
557812edc857SStefano Zampini   }
5579674ae819SStefano Zampini   PetscFunctionReturn(0);
5580674ae819SStefano Zampini }
5581674ae819SStefano Zampini 
5582984c4197SStefano Zampini /* uncomment for testing purposes */
5583984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5584674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5585674ae819SStefano Zampini {
5586674ae819SStefano Zampini   PetscErrorCode    ierr;
5587674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5588674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5589674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5590984c4197SStefano Zampini   /* one and zero */
5591984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5592984c4197SStefano Zampini   /* space to store constraints and their local indices */
55939162d606SStefano Zampini   PetscScalar       *constraints_data;
55949162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
55959162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
55969162d606SStefano Zampini   PetscInt          *constraints_n;
5597984c4197SStefano Zampini   /* iterators */
5598b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5599984c4197SStefano Zampini   /* BLAS integers */
5600e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5601e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5602c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5603727cdba6SStefano Zampini   /* reuse */
56040e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
56050e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5606984c4197SStefano Zampini   /* change of basis */
5607b3d85658SStefano Zampini   PetscBool         qr_needed;
56089162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5609984c4197SStefano Zampini   /* auxiliary stuff */
561064efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
56118a0068c3SStefano Zampini   PetscInt          ncc;
5612984c4197SStefano Zampini   /* some quantities */
561345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5614a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
561557715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
5616984c4197SStefano Zampini 
5617674ae819SStefano Zampini   PetscFunctionBegin;
561857715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
56198e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
56208e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
56218e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
562216909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5623088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5624088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
56250e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
56260e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
56270e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
56280e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
56290e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5630088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5631cf5a6209SStefano Zampini 
5632cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
56339162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5634cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5635cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5636cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5637cf5a6209SStefano Zampini     PetscScalar  *array;
5638cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5639cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5640674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5641b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5642674ae819SStefano Zampini     PetscScalar  *work;
5643674ae819SStefano Zampini     PetscReal    *singular_vals;
5644674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5645674ae819SStefano Zampini     PetscReal    *rwork;
5646674ae819SStefano Zampini #endif
5647674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5648674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5649674ae819SStefano Zampini #else
5650964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5651964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5652674ae819SStefano Zampini #endif
5653674ae819SStefano Zampini 
5654674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5655d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5656e4d548c7SStefano Zampini     /* print some info */
56575c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5658e4d548c7SStefano Zampini       PetscInt nv;
5659e4d548c7SStefano Zampini 
5660c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5661e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5662e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5663e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5664e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5665e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5666e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5667e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5668e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5669e4d548c7SStefano Zampini     }
5670e4d548c7SStefano Zampini 
5671d06fc5fdSStefano Zampini     /* free unneeded index sets */
5672d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5673d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5674674ae819SStefano Zampini     }
5675d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5676d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5677d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5678d06fc5fdSStefano Zampini       }
5679d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5680d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5681d06fc5fdSStefano Zampini     }
5682d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5683d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5684d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5685d06fc5fdSStefano Zampini       }
5686d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5687d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5688d06fc5fdSStefano Zampini     }
568970022509SStefano Zampini 
5690674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5691674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5692674ae819SStefano Zampini     if (nearnullsp) {
5693674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5694f4ddd8eeSStefano Zampini       /* remove any stored info */
5695f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5696f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5697f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5698f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5699f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5700473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5701f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5702f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5703f4ddd8eeSStefano Zampini       }
5704984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5705984c4197SStefano Zampini       nnsp_size = 0;
5706674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5707674ae819SStefano Zampini     }
5708984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5709984c4197SStefano Zampini     max_constraints = nnsp_size;
5710984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5711984c4197SStefano Zampini 
5712674ae819SStefano Zampini     /*
5713674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
57149162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
57159162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
57169162d606SStefano Zampini          There can be multiple constraints per connected component
5717674ae819SStefano Zampini                                                                                                                                                            */
5718674ae819SStefano Zampini     n_vertices = 0;
5719674ae819SStefano Zampini     if (ISForVertices) {
5720674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5721674ae819SStefano Zampini     }
57229162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
57239162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
57249162d606SStefano Zampini 
57259162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
57269162d606SStefano Zampini     total_counts *= max_constraints;
5727674ae819SStefano Zampini     total_counts += n_vertices;
57284641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
57299162d606SStefano Zampini 
5730674ae819SStefano Zampini     total_counts = 0;
5731674ae819SStefano Zampini     max_size_of_constraint = 0;
5732674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
57339162d606SStefano Zampini       IS used_is;
5734674ae819SStefano Zampini       if (i<n_ISForEdges) {
57359162d606SStefano Zampini         used_is = ISForEdges[i];
5736674ae819SStefano Zampini       } else {
57379162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5738674ae819SStefano Zampini       }
57399162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5740674ae819SStefano Zampini       total_counts += j;
5741674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5742674ae819SStefano Zampini     }
57439162d606SStefano 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);
57449162d606SStefano Zampini 
5745984c4197SStefano Zampini     /* get local part of global near null space vectors */
5746785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5747984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5748984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5749e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5750e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5751984c4197SStefano Zampini     }
5752674ae819SStefano Zampini 
5753242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5754242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5755a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5756242a89d7SStefano Zampini 
5757984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5758a773dcb8SStefano Zampini     if (!skip_lapack) {
5759674ae819SStefano Zampini       PetscScalar temp_work;
5760911cabfeSStefano Zampini 
5761674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5762984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5763785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5764785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5765785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5766674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5767785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5768674ae819SStefano Zampini #endif
5769674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5770c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5771c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5772674ae819SStefano Zampini       lwork = -1;
5773674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5774674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5775c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5776674ae819SStefano Zampini #else
5777c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5778674ae819SStefano Zampini #endif
5779674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5780984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5781674ae819SStefano Zampini #else /* on missing GESVD */
5782674ae819SStefano Zampini       /* SVD */
5783674ae819SStefano Zampini       PetscInt max_n,min_n;
5784674ae819SStefano Zampini       max_n = max_size_of_constraint;
5785984c4197SStefano Zampini       min_n = max_constraints;
5786984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5787674ae819SStefano Zampini         min_n = max_size_of_constraint;
5788984c4197SStefano Zampini         max_n = max_constraints;
5789674ae819SStefano Zampini       }
5790785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5791674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5792785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5793674ae819SStefano Zampini #endif
5794674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5795674ae819SStefano Zampini       lwork = -1;
5796e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5797e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5798b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5799674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5800674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
58019162d606SStefano 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));
5802674ae819SStefano Zampini #else
58039162d606SStefano 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));
5804674ae819SStefano Zampini #endif
5805674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5806984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5807984c4197SStefano Zampini #endif /* on missing GESVD */
5808674ae819SStefano Zampini       /* Allocate optimal workspace */
5809674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5810854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5811674ae819SStefano Zampini     }
5812674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5813674ae819SStefano Zampini     total_counts = 0;
58149162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
58159162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5816674ae819SStefano Zampini     /* vertices */
58179162d606SStefano Zampini     if (n_vertices) {
5818674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
58199162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5820674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
58219162d606SStefano Zampini         constraints_n[total_counts] = 1;
58229162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
58239162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
58249162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5825674ae819SStefano Zampini         total_counts++;
5826674ae819SStefano Zampini       }
5827674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5828674ae819SStefano Zampini       n_vertices = total_counts;
5829674ae819SStefano Zampini     }
5830984c4197SStefano Zampini 
5831674ae819SStefano Zampini     /* edges and faces */
58329162d606SStefano Zampini     total_counts_cc = total_counts;
5833911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
58349162d606SStefano Zampini       IS        used_is;
58359162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
58369162d606SStefano Zampini 
5837911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
58389162d606SStefano Zampini         used_is = ISForEdges[ncc];
5839984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5840674ae819SStefano Zampini       } else {
58419162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5842984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5843674ae819SStefano Zampini       }
5844674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
58459162d606SStefano Zampini 
58469162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
58479162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5848984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5849984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5850674ae819SStefano Zampini       if (nnsp_has_cnst) {
58515b08dc53SStefano Zampini         PetscScalar quad_value;
58529162d606SStefano Zampini 
58539162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
58549162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
58559162d606SStefano Zampini 
5856a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5857674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5858a773dcb8SStefano Zampini         } else {
5859a773dcb8SStefano Zampini           quad_value = 1.0;
5860a773dcb8SStefano Zampini         }
5861674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
58629162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5863674ae819SStefano Zampini         }
58649162d606SStefano Zampini         temp_constraints++;
5865674ae819SStefano Zampini         total_counts++;
5866674ae819SStefano Zampini       }
5867674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5868984c4197SStefano Zampini         PetscReal real_value;
58699162d606SStefano Zampini         PetscScalar *ptr_to_data;
58709162d606SStefano Zampini 
5871984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
58729162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5873674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
58749162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5875674ae819SStefano Zampini         }
5876984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5877984c4197SStefano Zampini         /* check if array is null on the connected component */
5878e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
58799162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
588057715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
5881674ae819SStefano Zampini           temp_constraints++;
5882674ae819SStefano Zampini           total_counts++;
58839162d606SStefano Zampini           if (!idxs_copied) {
58849162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
58859162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5886674ae819SStefano Zampini           }
5887674ae819SStefano Zampini         }
58889162d606SStefano Zampini       }
58899162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
589045a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5891eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5892a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
58939162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
58949162d606SStefano Zampini 
58959162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5896a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
58979162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5898a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
58999162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5900a773dcb8SStefano Zampini         } else { /* perform SVD */
59019162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5902674ae819SStefano Zampini 
5903674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5904984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5905984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5906984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5907984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5908984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5909984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5910984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5911984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5912674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5913e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5914984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5915674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5916674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
59179162d606SStefano 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));
5918674ae819SStefano Zampini             }
5919674ae819SStefano Zampini           }
5920e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5921e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5922e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5923674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5924c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5925674ae819SStefano Zampini #else
5926c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5927674ae819SStefano Zampini #endif
5928674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5929984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5930984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5931674ae819SStefano Zampini           j = 0;
5932984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5933674ae819SStefano Zampini           total_counts = total_counts-j;
593445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5935e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5936c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5937c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5938c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5939c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5940c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5941c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5942674ae819SStefano Zampini           if (j<temp_constraints) {
5943984c4197SStefano Zampini             PetscInt ii;
5944984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5945674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
59469162d606SStefano 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));
5947674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5948984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5949674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
59509162d606SStefano 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];
5951674ae819SStefano Zampini               }
5952674ae819SStefano Zampini             }
5953674ae819SStefano Zampini           }
5954674ae819SStefano Zampini #else  /* on missing GESVD */
5955e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5956e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5957b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5958674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5959674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
59609162d606SStefano 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));
5961674ae819SStefano Zampini #else
59629162d606SStefano 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));
5963674ae819SStefano Zampini #endif
5964984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5965674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5966984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5967e310c8b4SStefano Zampini           k = temp_constraints;
5968e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5969674ae819SStefano Zampini           j = 0;
5970e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
597145a1bb75SStefano Zampini           valid_constraints = k-j;
5972911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5973984c4197SStefano Zampini #endif /* on missing GESVD */
5974674ae819SStefano Zampini         }
5975a773dcb8SStefano Zampini       }
59769162d606SStefano Zampini       /* update pointers information */
59779162d606SStefano Zampini       if (valid_constraints) {
59789162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
59799162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
59809162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
59819162d606SStefano Zampini         /* set change_of_basis flag */
598245a1bb75SStefano Zampini         if (boolforchange) {
5983b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
59849162d606SStefano Zampini         }
5985b3d85658SStefano Zampini         total_counts_cc++;
598645a1bb75SStefano Zampini       }
598745a1bb75SStefano Zampini     }
5988984c4197SStefano Zampini     /* free workspace */
59898f1c130eSStefano Zampini     if (!skip_lapack) {
5990984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5991984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5992984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5993984c4197SStefano Zampini #endif
5994984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5995984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5996984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5997984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5998984c4197SStefano Zampini #endif
5999984c4197SStefano Zampini     }
6000984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6001984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6002984c4197SStefano Zampini     }
6003984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6004cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6005cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6006cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6007cf5a6209SStefano Zampini     }
6008cf5a6209SStefano Zampini     if (n_ISForFaces) {
6009cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6010cf5a6209SStefano Zampini     }
6011cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6012cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6013cf5a6209SStefano Zampini     }
6014cf5a6209SStefano Zampini     if (n_ISForEdges) {
6015cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6016cf5a6209SStefano Zampini     }
6017cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
601808122e43SStefano Zampini   } else {
601908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6020984c4197SStefano Zampini 
602108122e43SStefano Zampini     total_counts = 0;
602208122e43SStefano Zampini     n_vertices = 0;
6023d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6024d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
602508122e43SStefano Zampini     }
602608122e43SStefano Zampini     max_constraints = 0;
60279162d606SStefano Zampini     total_counts_cc = 0;
602808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
602908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
60309162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
603108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
603208122e43SStefano Zampini     }
60339162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
60349162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
60359162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
60369162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
603774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
60389162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
60399162d606SStefano Zampini     total_counts_cc = 0;
60409162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
60419162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
60429162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
604308122e43SStefano Zampini       }
604408122e43SStefano Zampini     }
60459162d606SStefano Zampini #if 0
60469162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
60479162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
60489162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
60499162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
60509162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
60519162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
60529162d606SStefano Zampini       }
60539162d606SStefano Zampini       printf("\n");
60549162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
60559162d606SStefano Zampini     }
60561b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
60578bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
60581b968477SStefano Zampini     }
60591b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
60608bec7fa6SStefano 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]);
60611b968477SStefano Zampini     }
606208122e43SStefano Zampini #endif
606308122e43SStefano Zampini 
60648bec7fa6SStefano Zampini     max_size_of_constraint = 0;
60659162d606SStefano 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]);
60669162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
606708122e43SStefano Zampini     /* Change of basis */
6068b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
606908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
607008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
607108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6072b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
607308122e43SStefano Zampini         }
607408122e43SStefano Zampini       }
607508122e43SStefano Zampini     }
607608122e43SStefano Zampini   }
6077984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
60784f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
607908122e43SStefano Zampini 
60809162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
60819162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
6082eee23b56SStefano 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);
6083674ae819SStefano Zampini 
6084674ae819SStefano Zampini   /* Create constraint matrix */
6085674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
608616f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6087984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6088984c4197SStefano Zampini 
6089984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6090a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
6091a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
609274d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6093984c4197SStefano Zampini   total_primal_vertices=0;
6094b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
60959162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
60969162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
609772b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
60989162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6099b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
610064efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
61019162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
61029162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6103a717540cSStefano Zampini       }
6104b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
610591af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6106a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6107a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6108a717540cSStefano Zampini       }
6109fa434743SStefano Zampini     } else {
6110b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6111fa434743SStefano Zampini     }
6112a717540cSStefano Zampini   }
6113b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6114b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6115674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
611670022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
61174f1b2e48SStefano 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);
61180e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
61190e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6120984c4197SStefano Zampini 
6121984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
612274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6123785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6124984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
612574d5cdf7SStefano Zampini 
6126984c4197SStefano Zampini   j = total_primal_vertices;
612774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6128b3d85658SStefano Zampini   cum = total_primal_vertices;
61299162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
61304641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6131b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6132b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6133b3d85658SStefano Zampini       cum++;
61349162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
613574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
613674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
613774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
613874d5cdf7SStefano Zampini       }
61399162d606SStefano Zampini       j += constraints_n[i];
6140674ae819SStefano Zampini     }
6141674ae819SStefano Zampini   }
6142674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6143674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6144088faed8SStefano Zampini 
6145674ae819SStefano Zampini   /* set values in constraint matrix */
6146984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
61470e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6148674ae819SStefano Zampini   }
6149984c4197SStefano Zampini   total_counts = total_primal_vertices;
61509162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
61514641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
61529162d606SStefano Zampini       PetscInt *cols;
61539162d606SStefano Zampini 
61549162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
61559162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
61569162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
61579162d606SStefano Zampini         PetscInt    row = total_counts+k;
61589162d606SStefano Zampini         PetscScalar *vals;
61599162d606SStefano Zampini 
61609162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
61619162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
61629162d606SStefano Zampini       }
61639162d606SStefano Zampini       total_counts += constraints_n[i];
6164674ae819SStefano Zampini     }
6165674ae819SStefano Zampini   }
6166674ae819SStefano Zampini   /* assembling */
6167674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6168674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
61693272d46bSStefano Zampini   ierr = MatChop(pcbddc->ConstraintMatrix,PETSC_SMALL);CHKERRQ(ierr);
61703272d46bSStefano Zampini   ierr = MatSeqAIJCompress(pcbddc->ConstraintMatrix,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
61713272d46bSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,NULL,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6172088faed8SStefano Zampini 
6173984c4197SStefano Zampini   /*
61746a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6175984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
6176f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
6177984c4197SStefano Zampini   */
6178674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6179674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6180026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6181984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6182984c4197SStefano Zampini     /* working stuff for GEQRF */
618381d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
6184984c4197SStefano Zampini     PetscBLASInt lqr_work;
6185984c4197SStefano Zampini     /* working stuff for UNGQR */
6186984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
6187984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6188984c4197SStefano Zampini     /* working stuff for TRTRS */
6189984c4197SStefano Zampini     PetscScalar  *trs_rhs;
61903f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6191984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6192984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6193984c4197SStefano Zampini     PetscScalar  *start_vals;
6194984c4197SStefano Zampini     /* working stuff for values insertion */
61954641a718SStefano Zampini     PetscBT      is_primal;
619664efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6197906d46d4SStefano Zampini     /* matrix sizes */
6198906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6199906d46d4SStefano Zampini     /* temporary change of basis */
6200906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6201cf5a6209SStefano Zampini     /* extra space for debugging */
6202cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
6203984c4197SStefano Zampini 
6204906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6205906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
620616f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6207bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6208906d46d4SStefano Zampini     /* nonzeros for local mat */
6209bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
62101dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6211bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
62121dd7afcfSStefano Zampini     } else {
62131dd7afcfSStefano Zampini       const PetscInt *ii;
62141dd7afcfSStefano Zampini       PetscInt       n;
62151dd7afcfSStefano Zampini       PetscBool      flg_row;
62161dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
62171dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
62181dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
62191dd7afcfSStefano Zampini     }
62209162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6221a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
62229162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6223a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
62249162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6225a717540cSStefano Zampini         } else {
62269162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
62279162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6228a717540cSStefano Zampini         }
6229a717540cSStefano Zampini       }
6230a717540cSStefano Zampini     }
6231906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6232bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
62331dd7afcfSStefano Zampini     /* Set interior change in the matrix */
62341dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6235bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6236906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6237a717540cSStefano Zampini       }
62381dd7afcfSStefano Zampini     } else {
62391dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
62401dd7afcfSStefano Zampini       PetscScalar    *aa;
62411dd7afcfSStefano Zampini       PetscInt       n;
62421dd7afcfSStefano Zampini       PetscBool      flg_row;
62431dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
62441dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
62451dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
62461dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
62471dd7afcfSStefano Zampini       }
62481dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
62491dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
62501dd7afcfSStefano Zampini     }
6251a717540cSStefano Zampini 
6252a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6253a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6254a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6255a717540cSStefano Zampini     }
6256a717540cSStefano Zampini 
6257a717540cSStefano Zampini 
6258a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6259a717540cSStefano Zampini     /*
6260a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6261a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6262a717540cSStefano Zampini 
6263a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6264a717540cSStefano Zampini 
6265a6b551f4SStefano 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)
6266a6b551f4SStefano Zampini 
6267a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6268a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6269a717540cSStefano Zampini             |              ...                        |
6270a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6271a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6272a717540cSStefano Zampini 
6273a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6274a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6275a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6276a6b551f4SStefano Zampini 
6277a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6278a717540cSStefano Zampini     */
6279a717540cSStefano Zampini     if (qr_needed) {
6280984c4197SStefano Zampini       /* space to store Q */
6281854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
62824e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
62834e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6284984c4197SStefano Zampini       /* first we issue queries for optimal work */
62853f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
62863f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
62873f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6288984c4197SStefano Zampini       lqr_work = -1;
62893f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6290984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6291984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6292785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6293984c4197SStefano Zampini       lgqr_work = -1;
62943f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
62953f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
62963f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
62973f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62983f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6299c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6300c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6301984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6302785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6303984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6304785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6305a717540cSStefano Zampini       /* allocating workspace for check */
6306a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6307cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6308a717540cSStefano Zampini       }
6309a717540cSStefano Zampini     }
6310984c4197SStefano Zampini     /* array to store whether a node is primal or not */
63114641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6312473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
63130e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
6314eee23b56SStefano 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);
631539e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
631639e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
631739e2fb2aSStefano Zampini     }
631839e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6319984c4197SStefano Zampini 
6320a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
63219162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
63229162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
63234641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6324984c4197SStefano Zampini         /* get constraint info */
63259162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6326984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6327984c4197SStefano Zampini 
6328984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
63299162d606SStefano 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);
6330674ae819SStefano Zampini         }
6331984c4197SStefano Zampini 
6332fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6333a717540cSStefano Zampini 
6334a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6335a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
63369162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6337a717540cSStefano Zampini           }
6338984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
63399162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6340984c4197SStefano Zampini 
6341984c4197SStefano Zampini           /* compute QR decomposition of constraints */
63423f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
63433f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
63443f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6345674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63463f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6347984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6348674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6349984c4197SStefano Zampini 
6350984c4197SStefano Zampini           /* explictly compute R^-T */
6351984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6352984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
63533f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
63543f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
63553f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
63563f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6357984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63583f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6359984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6360984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6361984c4197SStefano Zampini 
6362a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
63633f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
63643f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63653f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
63663f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6367984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6368c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6369c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6370984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6371984c4197SStefano Zampini 
6372984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6373984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6374984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
63753f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
63763f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
63773f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
63783f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
63793f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
63803f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6381984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63829162d606SStefano 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));
6383984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
63849162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6385984c4197SStefano Zampini 
6386984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
63879162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6388984c4197SStefano Zampini           /* insert cols for primal dofs */
6389984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6390984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
63919162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6392906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6393984c4197SStefano Zampini           }
6394984c4197SStefano Zampini           /* insert cols for dual dofs */
6395984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
63969162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6397984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
63989162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6399906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6400984c4197SStefano Zampini               j++;
6401674ae819SStefano Zampini             }
6402674ae819SStefano Zampini           }
6403984c4197SStefano Zampini 
6404984c4197SStefano Zampini           /* check change of basis */
6405984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6406984c4197SStefano Zampini             PetscInt   ii,jj;
6407984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6408c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6409c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6410c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6411c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6412c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6413c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6414984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6415cf5a6209SStefano 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));
6416984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6417984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6418984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6419cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6420c068d9bbSLisandro 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;
6421674ae819SStefano Zampini               }
6422674ae819SStefano Zampini             }
6423984c4197SStefano Zampini             if (!valid_qr) {
642422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6425984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6426984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6427cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6428cf5a6209SStefano 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]));
6429674ae819SStefano Zampini                   }
6430c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
6431cf5a6209SStefano 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]));
6432984c4197SStefano Zampini                   }
6433984c4197SStefano Zampini                 }
6434984c4197SStefano Zampini               }
6435674ae819SStefano Zampini             } else {
643622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6437674ae819SStefano Zampini             }
6438674ae819SStefano Zampini           }
6439a717540cSStefano Zampini         } else { /* simple transformation block */
6440a717540cSStefano Zampini           PetscInt    row,col;
6441a6b551f4SStefano Zampini           PetscScalar val,norm;
6442a6b551f4SStefano Zampini 
6443a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
64449162d606SStefano 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));
6445a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
64469162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
64479162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6448bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
64499162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6450906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
64519162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6452a717540cSStefano Zampini             } else {
6453a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
64549162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6455a717540cSStefano Zampini                 if (row != col) {
64569162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6457a717540cSStefano Zampini                 } else {
64589162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6459a717540cSStefano Zampini                 }
6460906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6461a717540cSStefano Zampini               }
6462a717540cSStefano Zampini             }
6463a717540cSStefano Zampini           }
646498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
646522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6466a717540cSStefano Zampini           }
6467674ae819SStefano Zampini         }
6468984c4197SStefano Zampini       } else {
6469984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
64709162d606SStefano 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);
6471674ae819SStefano Zampini         }
6472674ae819SStefano Zampini       }
6473674ae819SStefano Zampini     }
6474a717540cSStefano Zampini 
6475a717540cSStefano Zampini     /* free workspace */
6476a717540cSStefano Zampini     if (qr_needed) {
6477984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6478cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6479984c4197SStefano Zampini       }
6480984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6481984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6482984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6483984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6484984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6485674ae819SStefano Zampini     }
6486a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6487906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6488906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6489906d46d4SStefano Zampini 
6490906d46d4SStefano Zampini     /* assembling of global change of variable */
649188c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6492bbb9e6c6SStefano Zampini       Mat      tmat;
649316f15bc4SStefano Zampini       PetscInt bs;
649416f15bc4SStefano Zampini 
6495906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6496906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6497bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6498bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6499bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6500bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
650116f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
650216f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6503906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6504bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6505bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6506bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6507bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6508bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6509e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6510e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6511bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6512bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
651388c03ad3SStefano Zampini 
6514906d46d4SStefano Zampini       /* check */
6515906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6516906d46d4SStefano Zampini         PetscReal error;
6517906d46d4SStefano Zampini         Vec       x,x_change;
6518906d46d4SStefano Zampini 
6519906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6520906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6521906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6522906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6523e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6524e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6525bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6526e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6527e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6528906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6529906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6530906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6531637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6532637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6533637e8532SStefano Zampini         }
6534906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6535906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6536906d46d4SStefano Zampini       }
6537b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6538b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6539b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6540bf3a8328SStefano Zampini 
654113903a91SSatish 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");
6542b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6543ac632422SStefano Zampini           Mat                    S_new,tmat;
6544bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6545bbb9e6c6SStefano Zampini 
6546bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
65477dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6548bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6549bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6550bf3a8328SStefano Zampini             IS                     is_V;
6551b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6552b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6553b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6554b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6555b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6556bf3a8328SStefano Zampini           }
6557bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6558ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6559b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6560ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6561bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6562bf3a8328SStefano Zampini             const PetscScalar *array;
6563bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6564bf3a8328SStefano Zampini             PetscInt          i,n_V;
6565bf3a8328SStefano Zampini 
6566b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6567b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6568b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6569b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6570b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6571b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6572b087196eSStefano Zampini               PetscScalar val;
6573b087196eSStefano Zampini               PetscInt    idx;
6574b087196eSStefano Zampini 
6575b087196eSStefano Zampini               idx = idxs_V[i];
6576b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6577b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6578b087196eSStefano Zampini             }
6579b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6580b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6581bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6582bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6583bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6584bf3a8328SStefano Zampini           }
6585ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6586ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6587ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6588ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6589b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6590ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6591bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6592b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6593bf3a8328SStefano Zampini             }
6594ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6595ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6596ac632422SStefano Zampini           }
6597b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
659888c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6599b96c3477SStefano Zampini         }
6600c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6601b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6602c9db6a07SStefano Zampini           PetscInt i;
6603c9db6a07SStefano Zampini 
6604c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6605c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6606c9db6a07SStefano Zampini           }
6607c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6608c9db6a07SStefano Zampini         }
6609b96c3477SStefano Zampini       }
661016909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
661116909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
661216909a7fSStefano Zampini       } else {
6613906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
661416909a7fSStefano Zampini       }
66151dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
661627b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
661772b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
661872b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
661972b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
662072b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
662172b8c272SStefano Zampini     }
66221dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
662327b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6624b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6625b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6626906d46d4SStefano Zampini     } else {
66271dd7afcfSStefano Zampini       Mat benign_global = NULL;
662827b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
66291dd7afcfSStefano Zampini         Mat tmat;
66301dd7afcfSStefano Zampini 
66311dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
66321dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
66331dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
66341dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
66351dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
66361dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
66371dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
66381dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
66391dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
66401dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
66411dd7afcfSStefano Zampini           Mat M;
66421dd7afcfSStefano Zampini 
66431dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
66441dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
66451dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
66461dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6647906d46d4SStefano Zampini         } else {
66481dd7afcfSStefano Zampini           Mat         eye;
66491dd7afcfSStefano Zampini           PetscScalar *array;
66501dd7afcfSStefano Zampini 
66511dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
66521dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
66531dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
66541dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6655906d46d4SStefano Zampini           }
66561dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
66571dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66581dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66591dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
66601dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
66611dd7afcfSStefano Zampini         }
66621dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
66631dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
66641dd7afcfSStefano Zampini       }
66651dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
66661dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
66671dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
666827b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
66691dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
66701dd7afcfSStefano Zampini       }
66711dd7afcfSStefano Zampini     }
667216909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
667316909a7fSStefano Zampini       IS             is_global;
667416909a7fSStefano Zampini       const PetscInt *gidxs;
667516909a7fSStefano Zampini 
667616909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
667716909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
667816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
66797dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
668016909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
668116909a7fSStefano Zampini     }
66821dd7afcfSStefano Zampini   }
66831dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
66841dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6685b9b85e73SStefano Zampini   }
6686a717540cSStefano Zampini 
668772b8c272SStefano Zampini   if (!pcbddc->fake_change) {
66884f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
66894f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66904f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
66914f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6692019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6693019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6694019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6695019a44ceSStefano Zampini     }
6696019a44ceSStefano Zampini 
6697019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6698727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6699727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
67009f47a83aSStefano 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);
6701c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
67020e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
67039f47a83aSStefano 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);
6704727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6705727cdba6SStefano Zampini       }
67060e6343abSStefano Zampini     }
6707727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6708b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
670972b8c272SStefano Zampini   }
671072b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6711727cdba6SStefano Zampini 
6712a717540cSStefano Zampini   /* flush dbg viewer */
6713b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6714b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6715b8ffe317SStefano Zampini   }
6716a717540cSStefano Zampini 
6717e310c8b4SStefano Zampini   /* free workspace */
6718a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
67194641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
672008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
67219162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
67229162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
672308122e43SStefano Zampini   } else {
67249162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
67259162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
67269162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
672708122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
672808122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
67299162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
67309162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
673108122e43SStefano Zampini   }
6732674ae819SStefano Zampini   PetscFunctionReturn(0);
6733674ae819SStefano Zampini }
673404a6f24aSStefano Zampini /* #undef PETSC_MISSING_LAPACK_GESVD */
6735674ae819SStefano Zampini 
6736674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6737674ae819SStefano Zampini {
673871582508SStefano Zampini   ISLocalToGlobalMapping map;
6739674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6740674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
674166da6bd7Sstefano_zampini   PetscInt               i,N;
674266da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
674366da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6744674ae819SStefano Zampini 
6745674ae819SStefano Zampini   PetscFunctionBegin;
67468af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6747b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
67488e61c736SStefano Zampini     /* Reset previously computed graph */
67498e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6750674ae819SStefano Zampini     /* Init local Graph struct */
67517fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
675271582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6753be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6754674ae819SStefano Zampini 
67557a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
67567a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
67577a0e7b2cSstefano_zampini     }
6758575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
6759ab8c8b98SStefano 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);
67609577ea80SStefano Zampini 
6761674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
676266da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
67634d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
67644d379d7bSStefano Zampini       PetscInt  nvtxs;
6765e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6766674ae819SStefano Zampini 
67672fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
67682fffb893SStefano Zampini       if (flg_row) {
67694d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6770b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
67712fffb893SStefano Zampini       }
67722fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
677366da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6774674ae819SStefano Zampini     }
67759b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
67769b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6777674ae819SStefano Zampini     }
6778674ae819SStefano Zampini 
6779ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
6780ab8c8b98SStefano Zampini       PetscReal    *lcoords;
6781ab8c8b98SStefano Zampini       PetscInt     n;
6782ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
6783ab8c8b98SStefano Zampini 
6784ab8c8b98SStefano 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);
6785ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
6786ab8c8b98SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
6787ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
6788ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
6789ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
6790ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6791ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6792ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
6793ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
6794ab8c8b98SStefano Zampini 
6795ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
6796ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
6797ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
6798ab8c8b98SStefano Zampini     }
6799ab8c8b98SStefano 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);
6800ab8c8b98SStefano Zampini 
6801674ae819SStefano Zampini     /* Setup of Graph */
68024b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
680314f95afaSStefano 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);
6804674ae819SStefano Zampini 
68054f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
68064f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
68074f1b2e48SStefano Zampini       PetscInt *local_subs;
68084f1b2e48SStefano Zampini 
68094f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
68104f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
68114f1b2e48SStefano Zampini         const PetscInt *idxs;
68124f1b2e48SStefano Zampini         PetscInt       nl,j;
68134f1b2e48SStefano Zampini 
68144f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
68154f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
681671582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
68174f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
68184f1b2e48SStefano Zampini       }
68194f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
68204f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
68214f1b2e48SStefano Zampini     }
68228af8fcf9SStefano Zampini   }
68234f1b2e48SStefano Zampini 
6824cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6825674ae819SStefano Zampini     /* Graph's connected components analysis */
6826674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
682771582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
68288af8fcf9SStefano Zampini   }
682966da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6830674ae819SStefano Zampini   PetscFunctionReturn(0);
6831674ae819SStefano Zampini }
6832674ae819SStefano Zampini 
68339a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
68349a7d3425SStefano Zampini {
68359a7d3425SStefano Zampini   PetscInt       i,j;
68369a7d3425SStefano Zampini   PetscScalar    *alphas;
68379a7d3425SStefano Zampini   PetscErrorCode ierr;
68389a7d3425SStefano Zampini 
68399a7d3425SStefano Zampini   PetscFunctionBegin;
6840785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
68419a7d3425SStefano Zampini   for (i=0;i<n;i++) {
68429a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6843669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6844669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6845669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
68469a7d3425SStefano Zampini   }
68479a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
68489a7d3425SStefano Zampini   PetscFunctionReturn(0);
68499a7d3425SStefano Zampini }
68509a7d3425SStefano Zampini 
6851bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6852e7931f94SStefano Zampini {
685357de7509SStefano Zampini   Mat            A;
6854e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6855e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
685652e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
685752e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6858bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
685957de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
686027b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
686127b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
686227b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
686327b6a85dSStefano Zampini   MPI_Comm       subcomm;
686452e5ac9dSStefano Zampini   PetscErrorCode ierr;
6865a57a6d2fSStefano Zampini 
6866e7931f94SStefano Zampini   PetscFunctionBegin;
686757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
686857de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6869fbfcfee5SBarry 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);
687057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
687157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
687257de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
687357de7509SStefano Zampini 
687457de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
687557de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
687657de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
687757de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
687857de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6879bb360cb4SStefano Zampini   im_active = !!n;
688057de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
688157de7509SStefano Zampini   void_procs = size - active_procs;
688257de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
688357de7509SStefano Zampini   if (void_procs) {
688457de7509SStefano Zampini     PetscInt ncand;
688557de7509SStefano Zampini 
688657de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
688757de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
688857de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
688957de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
689057de7509SStefano Zampini       if (!procs_candidates[i]) {
689157de7509SStefano Zampini         procs_candidates[ncand++] = i;
689257de7509SStefano Zampini       }
689357de7509SStefano Zampini     }
689457de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
689557de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
689657de7509SStefano Zampini   }
689757de7509SStefano Zampini 
6898bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
689914f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
6900bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
6901bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
690214f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
690314f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
690414f0bfb9SStefano Zampini     else dest = rank;
690557de7509SStefano Zampini     if (im_active) {
690657de7509SStefano Zampini       issize = 1;
690757de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
690814f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
690957de7509SStefano Zampini       } else {
691014f0bfb9SStefano Zampini         isidx = dest;
691157de7509SStefano Zampini       }
691257de7509SStefano Zampini     } else {
691357de7509SStefano Zampini       issize = 0;
691457de7509SStefano Zampini       isidx = -1;
691557de7509SStefano Zampini     }
6916bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
691757de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6918daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
691957de7509SStefano Zampini     PetscFunctionReturn(0);
692057de7509SStefano Zampini   }
6921c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6922c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
692327b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6924e7931f94SStefano Zampini 
6925e7931f94SStefano Zampini   /* Get info on mapping */
69263bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6927e7931f94SStefano Zampini 
6928e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6929785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6930e7931f94SStefano Zampini   xadj[0] = 0;
6931e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6932785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6933785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
6934bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
693527b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
693627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
693727b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6938e7931f94SStefano Zampini 
693927b6a85dSStefano Zampini   xadj_count = 0;
69402b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
694127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
694227b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6943d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6944d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6945d023bfaeSStefano Zampini         xadj_count++;
694627b6a85dSStefano Zampini         break;
694727b6a85dSStefano Zampini       }
6948e7931f94SStefano Zampini     }
6949e7931f94SStefano Zampini   }
6950d023bfaeSStefano Zampini   xadj[1] = xadj_count;
695127b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
69523bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6953e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6954e7931f94SStefano Zampini 
69553837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6956e7931f94SStefano Zampini 
695727b6a85dSStefano Zampini   /* Restrict work on active processes only */
695827b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
695927b6a85dSStefano Zampini   if (void_procs) {
696027b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
696127b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
696227b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
696327b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
696427b6a85dSStefano Zampini   } else {
696527b6a85dSStefano Zampini     psubcomm = NULL;
696627b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
696727b6a85dSStefano Zampini   }
696827b6a85dSStefano Zampini 
696927b6a85dSStefano Zampini   v_wgt = NULL;
697027b6a85dSStefano Zampini   if (!color) {
6971e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6972e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6973e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6974c8587f34SStefano Zampini   } else {
697552e5ac9dSStefano Zampini     Mat             subdomain_adj;
697652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
697752e5ac9dSStefano Zampini     MatPartitioning partitioner;
697827b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
697952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
698057de7509SStefano Zampini     PetscMPIInt     size;
6981b0c7d250SStefano Zampini     PetscBool       aggregate;
6982b0c7d250SStefano Zampini 
698327b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
698427b6a85dSStefano Zampini     if (void_procs) {
698527b6a85dSStefano Zampini       PetscInt prank = rank;
6986785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
698727b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6988e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6989e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6990c8587f34SStefano Zampini       }
6991e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
699227b6a85dSStefano Zampini     } else {
699327b6a85dSStefano Zampini       oldranks = NULL;
699427b6a85dSStefano Zampini     }
6995b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
699627b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6997b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6998b0c7d250SStefano Zampini       PetscMPIInt nrank;
6999b0c7d250SStefano Zampini       PetscScalar *vals;
7000b0c7d250SStefano Zampini 
700127b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7002b0c7d250SStefano Zampini       lrows = 0;
7003b0c7d250SStefano Zampini       if (nrank<redprocs) {
7004b0c7d250SStefano Zampini         lrows = size/redprocs;
7005b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7006b0c7d250SStefano Zampini       }
700727b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7008b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7009b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7010b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7011b0c7d250SStefano Zampini       row = nrank;
7012b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7013b0c7d250SStefano Zampini       cols = adjncy;
7014b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7015b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7016b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7017b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7018b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
701952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
702052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
702152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7022b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
702327b6a85dSStefano Zampini       if (use_vwgt) {
702427b6a85dSStefano Zampini         Vec               v;
702527b6a85dSStefano Zampini         const PetscScalar *array;
702627b6a85dSStefano Zampini         PetscInt          nl;
702727b6a85dSStefano Zampini 
702827b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7029bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
703027b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
703127b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
703227b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
703327b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
703427b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
703522db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
703627b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
703727b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
703827b6a85dSStefano Zampini       }
7039b0c7d250SStefano Zampini     } else {
704027b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
704127b6a85dSStefano Zampini       if (use_vwgt) {
704227b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7043bb360cb4SStefano Zampini         v_wgt[0] = n;
704427b6a85dSStefano Zampini       }
7045b0c7d250SStefano Zampini     }
704622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7047e7931f94SStefano Zampini 
7048e7931f94SStefano Zampini     /* Partition */
704927b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7050e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
705127b6a85dSStefano Zampini     if (v_wgt) {
7052e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7053c8587f34SStefano Zampini     }
705457de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
705557de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7056e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7057e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
705822b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7059e7931f94SStefano Zampini 
706052e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
70616583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
706252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
706352e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
706457de7509SStefano Zampini     if (!aggregate) {
706557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
706627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
706727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
706827b6a85dSStefano Zampini #endif
706957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
707027b6a85dSStefano Zampini       } else if (oldranks) {
7071b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
707227b6a85dSStefano Zampini       } else {
707327b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
707457de7509SStefano Zampini       }
707528143c3dSStefano Zampini     } else {
70767fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7077b0c7d250SStefano Zampini       PetscMPIInt tag;
7078b0c7d250SStefano Zampini       MPI_Request *reqs;
7079b0c7d250SStefano Zampini 
7080b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7081b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7082b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
708327b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
708428143c3dSStefano Zampini       }
70857fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7086b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7087b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
708857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
708927b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
709027b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
709127b6a85dSStefano Zampini #endif
70927fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
709327b6a85dSStefano Zampini       } else if (oldranks) {
70947fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
709527b6a85dSStefano Zampini       } else {
70967fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7097e7931f94SStefano Zampini       }
709857de7509SStefano Zampini     }
709952e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7100e7931f94SStefano Zampini     /* clean up */
7101e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
710252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7103e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7104e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7105e7931f94SStefano Zampini   }
710627b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
710757de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7108e7931f94SStefano Zampini 
7109e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7110e7931f94SStefano Zampini   i = 1;
711127b6a85dSStefano Zampini   if (!color) i=0;
711257de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7113e7931f94SStefano Zampini   PetscFunctionReturn(0);
7114e7931f94SStefano Zampini }
7115e7931f94SStefano Zampini 
7116e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7117e7931f94SStefano Zampini 
71181e0482f5SStefano 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[])
7119e7931f94SStefano Zampini {
712070cf5478SStefano Zampini   Mat                    local_mat;
7121e7931f94SStefano Zampini   IS                     is_sends_internal;
71229d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
71231ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
71249d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7125e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7126e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7127e7931f94SStefano Zampini   const PetscInt*        is_indices;
7128e7931f94SStefano Zampini   MatType                new_local_type;
7129e7931f94SStefano Zampini   /* buffers */
7130e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
713128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
71329d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
7133e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
71341ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7135e7931f94SStefano Zampini   /* MPI */
713628143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
713728143c3dSStefano Zampini   PetscSubcomm           subcomm;
7138e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
713928143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
714028143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
71411ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
71421ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
71431ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7144e7931f94SStefano Zampini   PetscErrorCode         ierr;
7145e7931f94SStefano Zampini 
7146e7931f94SStefano Zampini   PetscFunctionBegin;
714757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7148e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7149fbfcfee5SBarry 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);
715057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
715157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
715257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
715357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
715457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
71551ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
71561ae86dd6SStefano Zampini   if (nvecs) {
71571ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
71581ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
71591ae86dd6SStefano Zampini   }
716057de7509SStefano Zampini   /* further checks */
7161e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7162e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7163e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7164e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7165e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
716657de7509SStefano Zampini   if (reuse && *mat_n) {
716770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
716857de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
716970cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
717028143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
717170cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
717270cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
717370cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
717470cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
717570cf5478SStefano Zampini   }
7176e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7177e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
717857de7509SStefano Zampini 
7179e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7180e7931f94SStefano Zampini   if (!is_sends) {
718128143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7182bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7183c8587f34SStefano Zampini   } else {
7184e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7185e7931f94SStefano Zampini     is_sends_internal = is_sends;
7186c8587f34SStefano Zampini   }
7187e7931f94SStefano Zampini 
7188e7931f94SStefano Zampini   /* get comm */
7189a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7190e7931f94SStefano Zampini 
7191e7931f94SStefano Zampini   /* compute number of sends */
7192e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7193e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7194e7931f94SStefano Zampini 
7195e7931f94SStefano Zampini   /* compute number of receives */
7196e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
7197785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
7198e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
7199e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7200e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7201e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7202e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7203e7931f94SStefano Zampini 
720428143c3dSStefano Zampini   /* restrict comm if requested */
720528143c3dSStefano Zampini   subcomm = 0;
720628143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
720728143c3dSStefano Zampini   if (restrict_comm) {
7208779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7209779c1cceSStefano Zampini 
721028143c3dSStefano Zampini     color = 0;
721153a05cb3SStefano Zampini     if (restrict_full) {
721253a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
721353a05cb3SStefano Zampini     } else {
721453a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
721553a05cb3SStefano Zampini     }
7216b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
721728143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
721828143c3dSStefano Zampini     /* check if reuse has been requested */
721957de7509SStefano Zampini     if (reuse) {
722028143c3dSStefano Zampini       if (*mat_n) {
722128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
722228143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
722328143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
722428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
722528143c3dSStefano Zampini       } else {
722628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
722728143c3dSStefano Zampini       }
722828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7229779c1cceSStefano Zampini       PetscMPIInt rank;
7230779c1cceSStefano Zampini 
7231779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
723228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
723328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
723428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7235306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
723628143c3dSStefano Zampini     }
723728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
723828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
723928143c3dSStefano Zampini   } else {
724028143c3dSStefano Zampini     comm_n = comm;
724128143c3dSStefano Zampini   }
724228143c3dSStefano Zampini 
7243e7931f94SStefano Zampini   /* prepare send/receive buffers */
7244785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
7245e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7246785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
7247e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
724828143c3dSStefano Zampini   if (nis) {
7249854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
725028143c3dSStefano Zampini   }
7251e7931f94SStefano Zampini 
725228143c3dSStefano Zampini   /* Get data from local matrices */
72536c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7254e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7255e7931f94SStefano Zampini     /*
7256e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7257e7931f94SStefano Zampini        send_buffer_idxs should contain:
7258e7931f94SStefano Zampini        - MatType_PRIVATE type
7259e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7260e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7261e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7262e7931f94SStefano Zampini     */
72636c4ed002SBarry Smith   else {
7264e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
72653bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7266854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7267e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7268e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
72693bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7270e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
72713bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7272e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7273e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7274e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7275e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7276c8587f34SStefano Zampini     }
7277c8587f34SStefano Zampini   }
7278e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
727928143c3dSStefano Zampini   /* additional is (if any) */
728028143c3dSStefano Zampini   if (nis) {
728128143c3dSStefano Zampini     PetscMPIInt psum;
728228143c3dSStefano Zampini     PetscInt j;
728328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
728428143c3dSStefano Zampini       PetscInt plen;
728528143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
728628143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
728728143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
728828143c3dSStefano Zampini     }
7289854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
729028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
729128143c3dSStefano Zampini       PetscInt plen;
729228143c3dSStefano Zampini       const PetscInt *is_array_idxs;
729328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
729428143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
729528143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
729628143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
729728143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
729828143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
729928143c3dSStefano Zampini     }
730028143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
730128143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
730228143c3dSStefano Zampini     }
730328143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
730428143c3dSStefano Zampini   }
73053b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
730628143c3dSStefano Zampini 
7307e7931f94SStefano Zampini   buf_size_idxs = 0;
7308e7931f94SStefano Zampini   buf_size_vals = 0;
730928143c3dSStefano Zampini   buf_size_idxs_is = 0;
73101ae86dd6SStefano Zampini   buf_size_vecs = 0;
7311e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7312e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7313e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
731428143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
73151ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7316e7931f94SStefano Zampini   }
7317785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7318785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
731995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
73201ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7321e7931f94SStefano Zampini 
7322e7931f94SStefano Zampini   /* get new tags for clean communications */
7323e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7324e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
732528143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
73261ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7327e7931f94SStefano Zampini 
7328e7931f94SStefano Zampini   /* allocate for requests */
7329785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7330785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
733195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
73321ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7333785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7334785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
733595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
73361ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7337e7931f94SStefano Zampini 
7338e7931f94SStefano Zampini   /* communications */
7339e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7340e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
734128143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
73421ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7343e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7344e7931f94SStefano Zampini     source_dest = onodes[i];
7345e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7346e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7347e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7348e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
734928143c3dSStefano Zampini     if (nis) {
735057de7509SStefano Zampini       source_dest = onodes_is[i];
735128143c3dSStefano 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);
735228143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
735328143c3dSStefano Zampini     }
73541ae86dd6SStefano Zampini     if (nvecs) {
73551ae86dd6SStefano Zampini       source_dest = onodes[i];
73561ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
73571ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
73581ae86dd6SStefano Zampini     }
7359e7931f94SStefano Zampini   }
7360e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7361e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7362e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7363e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
736428143c3dSStefano Zampini     if (nis) {
736528143c3dSStefano 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);
736628143c3dSStefano Zampini     }
73671ae86dd6SStefano Zampini     if (nvecs) {
73681ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
73691ae86dd6SStefano 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);
73701ae86dd6SStefano Zampini     }
7371e7931f94SStefano Zampini   }
7372e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7373e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7374e7931f94SStefano Zampini 
7375e7931f94SStefano Zampini   /* assemble new l2g map */
7376e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7377e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
73789d30be91SStefano Zampini   new_local_rows = 0;
7379e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
73809d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7381e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7382e7931f94SStefano Zampini   }
73839d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7384e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
73859d30be91SStefano Zampini   new_local_rows = 0;
7386e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
73879d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
73889d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7389e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7390e7931f94SStefano Zampini   }
73919d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
73929d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7393e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7394e7931f94SStefano Zampini 
7395e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7396e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7397e7931f94SStefano 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) */
7398e7931f94SStefano Zampini   if (n_recvs) {
739928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7400e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7401e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7402e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7403e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7404e7931f94SStefano Zampini         break;
7405e7931f94SStefano Zampini       }
7406e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7407e7931f94SStefano Zampini     }
7408e7931f94SStefano Zampini     switch (new_local_type_private) {
740928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7410e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7411e7931f94SStefano Zampini         bs = 1;
7412e7931f94SStefano Zampini         break;
7413e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7414e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7415e7931f94SStefano Zampini         bs = 1;
7416e7931f94SStefano Zampini         break;
7417e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7418e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7419e7931f94SStefano Zampini         break;
7420e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7421e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7422e7931f94SStefano Zampini         break;
7423e7931f94SStefano Zampini       default:
7424fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7425e7931f94SStefano Zampini         break;
7426e7931f94SStefano Zampini     }
7427ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7428ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
742928143c3dSStefano Zampini     bs = 1;
7430e7931f94SStefano Zampini   }
7431e7931f94SStefano Zampini 
743270cf5478SStefano Zampini   /* create MATIS object if needed */
743357de7509SStefano Zampini   if (!reuse) {
7434e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7435e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
743670cf5478SStefano Zampini   } else {
743770cf5478SStefano Zampini     /* it also destroys the local matrices */
743857de7509SStefano Zampini     if (*mat_n) {
743970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
744057de7509SStefano Zampini     } else { /* this is a fake object */
744157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
744257de7509SStefano Zampini     }
744370cf5478SStefano Zampini   }
744470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7445e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
74469d30be91SStefano Zampini 
74479d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
74489d30be91SStefano Zampini 
74499d30be91SStefano Zampini   /* Global to local map of received indices */
74509d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
74519d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
74529d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
74539d30be91SStefano Zampini 
74549d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
74559d30be91SStefano Zampini   buf_size_idxs = 0;
74569d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
74579d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
74589d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
74599d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
74609d30be91SStefano Zampini   }
74619d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
74629d30be91SStefano Zampini 
74639d30be91SStefano Zampini   /* set preallocation */
74649d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
74659d30be91SStefano Zampini   if (!newisdense) {
74669d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
74679d30be91SStefano Zampini 
74689d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
74699d30be91SStefano Zampini     if (n_recvs) {
74709d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
74719d30be91SStefano Zampini     }
74729d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
74739d30be91SStefano Zampini       PetscInt j;
74749d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
74759d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
74769d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
74779d30be91SStefano Zampini         }
74789d30be91SStefano Zampini       } else {
74799d30be91SStefano Zampini         /* TODO */
74809d30be91SStefano Zampini       }
74819d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
74829d30be91SStefano Zampini     }
74839d30be91SStefano Zampini     if (new_local_nnz) {
74849d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
74859d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
74869d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
74879d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
74889d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
74899d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
74909d30be91SStefano Zampini     } else {
74919d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
74929d30be91SStefano Zampini     }
74939d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
74949d30be91SStefano Zampini   } else {
74959d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
74969d30be91SStefano Zampini   }
7497e7931f94SStefano Zampini 
7498e7931f94SStefano Zampini   /* set values */
7499e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
75009d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7501e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7502e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7503e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
75049d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7505e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7506e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7507e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
750828143c3dSStefano Zampini     } else {
750928143c3dSStefano Zampini       /* TODO */
7510e7931f94SStefano Zampini     }
7511e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7512e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7513e7931f94SStefano Zampini   }
7514e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7515e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
75163b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
751770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
751870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
75199d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7520e7931f94SStefano Zampini 
7521dfd14d43SStefano Zampini #if 0
752228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7523e7931f94SStefano Zampini     Vec       lvec,rvec;
7524e7931f94SStefano Zampini     PetscReal infty_error;
7525e7931f94SStefano Zampini 
75262a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7527e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7528e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7529e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
753070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7531e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7532e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7533e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7534e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7535e7931f94SStefano Zampini   }
753628143c3dSStefano Zampini #endif
7537e7931f94SStefano Zampini 
753828143c3dSStefano Zampini   /* assemble new additional is (if any) */
753928143c3dSStefano Zampini   if (nis) {
754028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
754128143c3dSStefano Zampini 
754228143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7543854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
754428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
754528143c3dSStefano Zampini     psum = 0;
754628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
754728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
754828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
754928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
755028143c3dSStefano Zampini         psum += plen;
755128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
755228143c3dSStefano Zampini       }
755328143c3dSStefano Zampini     }
7554854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7555854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
755628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
755728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
755828143c3dSStefano Zampini     }
755928143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
756028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
756128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
756228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
756328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
756428143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
756528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
756628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
756728143c3dSStefano Zampini       }
756828143c3dSStefano Zampini     }
756928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
757028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
757128143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
757228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
757328143c3dSStefano Zampini     }
757428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
757528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
757628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
757728143c3dSStefano Zampini   }
7578e7931f94SStefano Zampini   /* free workspace */
757928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7580e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7581e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7582e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7583e7931f94SStefano Zampini   if (isdense) {
7584e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7585e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
75863b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7587e7931f94SStefano Zampini   } else {
7588e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7589e7931f94SStefano Zampini   }
759028143c3dSStefano Zampini   if (nis) {
759128143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
759228143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
759328143c3dSStefano Zampini   }
75941ae86dd6SStefano Zampini 
75951ae86dd6SStefano Zampini   if (nvecs) {
75961ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
75971ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
75981ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
75991ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
76001ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
76011ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
76021ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
76031ae86dd6SStefano Zampini     /* set values */
76041ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
76051ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
76061ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
76071ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
76081ae86dd6SStefano Zampini       PetscInt j;
76091ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
76101ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
76111ae86dd6SStefano Zampini       }
76121ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
76131ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
76141ae86dd6SStefano Zampini     }
76151ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
76161ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
76171ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
76181ae86dd6SStefano Zampini   }
76191ae86dd6SStefano Zampini 
76201ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
76211ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7622e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7623e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
76241ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
762528143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7626e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7627e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
76281ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
762928143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7630e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7631e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7632e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7633e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7634e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
763528143c3dSStefano Zampini   if (nis) {
763628143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
763728143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
763828143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
763928143c3dSStefano Zampini   }
764028143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
764128143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
764228143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
764328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
764428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
764528143c3dSStefano Zampini     }
76461ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
76471ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
76481ae86dd6SStefano Zampini     }
764953a05cb3SStefano Zampini     *mat_n = NULL;
765028143c3dSStefano Zampini   }
7651e7931f94SStefano Zampini   PetscFunctionReturn(0);
7652e7931f94SStefano Zampini }
7653a57a6d2fSStefano Zampini 
765412edc857SStefano Zampini /* temporary hack into ksp private data structure */
7655af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
765612edc857SStefano Zampini 
7657c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7658c8587f34SStefano Zampini {
7659c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7660c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
766120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
76621ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
76631e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
76649881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
766520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
76666e683305SStefano Zampini   IS                     coarse_is,*isarray;
76676e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
766830368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7669f9eb5b7dSStefano Zampini   PC                     pc_temp;
7670c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7671c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7672f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
76737274672aSStefano Zampini   PetscBool              coarse_reuse;
76741e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
767568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
767622bc73bbSStefano Zampini   PetscScalar            *array;
767757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
767857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
76797de4f681Sstefano_zampini   PetscMPIInt            commsize;
76809881197aSStefano Zampini   PetscErrorCode         ierr;
7681fdc09c96SStefano Zampini 
7682c8587f34SStefano Zampini   PetscFunctionBegin;
7683c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
768468457ee5SStefano 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 */
7685fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
76865a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
76877de4f681Sstefano_zampini 
76887de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7689fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7690f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7691f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7692f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7693fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
769451bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
769551bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7696727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7697fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7698fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7699fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7700f4ddd8eeSStefano Zampini       }
7701fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7702fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7703f4ddd8eeSStefano Zampini     }
770470cf5478SStefano Zampini     /* reset any subassembling information */
770557de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
770670cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
770757de7509SStefano Zampini     }
77086e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7709fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7710f4ddd8eeSStefano Zampini   }
771157de7509SStefano Zampini   /* assemble coarse matrix */
771257de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
771357de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
771457de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
771557de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
771618a45a71SStefano Zampini   } else {
771757de7509SStefano Zampini     coarse_mat = NULL;
771857de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
77196e683305SStefano Zampini   }
7720e7931f94SStefano Zampini 
7721abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7722abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7723abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7724abbbba34SStefano Zampini 
7725abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
772622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
772722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
772822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
772922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7730e176bc59SStefano 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);
77316e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
77326e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
77336e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7734abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7735abbbba34SStefano Zampini 
773657de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
773757de7509SStefano Zampini   im_active = !!(pcis->n);
773857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
773957de7509SStefano Zampini 
774014f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
774157de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
774257de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
77437de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
774457de7509SStefano Zampini   coarse_mat_is = NULL;
774557de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
774657de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
77471ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
774857de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
774957de7509SStefano Zampini   if (multilevel_requested) {
775057de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
775157de7509SStefano Zampini     restr = PETSC_FALSE;
775257de7509SStefano Zampini     full_restr = PETSC_FALSE;
775357de7509SStefano Zampini   } else {
775457de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
775557de7509SStefano Zampini     restr = PETSC_TRUE;
775657de7509SStefano Zampini     full_restr = PETSC_TRUE;
775757de7509SStefano Zampini   }
77587de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
775957de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
776057de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7761a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7762bb360cb4SStefano Zampini       if (multilevel_requested) {
7763bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7764bb360cb4SStefano Zampini       } else {
7765bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7766bb360cb4SStefano Zampini       }
7767a198735bSStefano Zampini     } else {
77687de4f681Sstefano_zampini       PetscMPIInt rank;
7769a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
77707de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7771a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7772a198735bSStefano Zampini     }
777357de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
777457de7509SStefano Zampini     PetscInt    psum;
777557de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
777657de7509SStefano Zampini     else psum = 0;
777757de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
77787de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
777957de7509SStefano Zampini   }
778057de7509SStefano Zampini   /* determine if we can go multilevel */
778157de7509SStefano Zampini   if (multilevel_requested) {
778257de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
778357de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
778457de7509SStefano Zampini   }
778557de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
778657de7509SStefano Zampini 
7787e4d548c7SStefano Zampini   /* dump subassembling pattern */
7788e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7789e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7790e4d548c7SStefano Zampini   }
7791e4d548c7SStefano Zampini 
77926e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
77931e0482f5SStefano Zampini   nedcfield = -1;
77941e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
77956e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
77966e683305SStefano Zampini     const PetscInt         *idxs;
77976e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
77986e683305SStefano Zampini 
77996e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
78000be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
78016e683305SStefano Zampini     /* allocate space for temporary storage */
7802854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7803854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
78046e683305SStefano Zampini     /* allocate for IS array */
78056e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
78061e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
78071e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
78081e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
78091e0482f5SStefano Zampini       } else {
78101e0482f5SStefano Zampini         nedcfield = 0;
78111e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
78121e0482f5SStefano Zampini         nisdofs = 1;
78131e0482f5SStefano Zampini       }
78141e0482f5SStefano Zampini     }
78156e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
781627b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
781730368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7818854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
78196e683305SStefano Zampini     /* dofs splitting */
78206e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
78216e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
78221e0482f5SStefano Zampini       if (nedcfield != i) {
78236e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
78246e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
78256e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
78266e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
78271e0482f5SStefano Zampini       } else {
78281e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
78291e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
78301e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7831eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
78321e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
78331e0482f5SStefano Zampini       }
78346e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
783530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
78366e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
78376e683305SStefano Zampini     }
78386e683305SStefano Zampini     /* neumann boundaries */
78396e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
78406e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
78416e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
78426e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
78436e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
78446e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
78456e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
784630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
78476e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
78486e683305SStefano Zampini     }
78496e683305SStefano Zampini     /* free memory */
78506e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
78516e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
78526e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
78536e683305SStefano Zampini   } else {
78546e683305SStefano Zampini     nis = 0;
78556e683305SStefano Zampini     nisdofs = 0;
78566e683305SStefano Zampini     nisneu = 0;
785730368db7SStefano Zampini     nisvert = 0;
78586e683305SStefano Zampini     isarray = NULL;
78596e683305SStefano Zampini   }
78606e683305SStefano Zampini   /* destroy no longer needed map */
78616e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
78626e683305SStefano Zampini 
786357de7509SStefano Zampini   /* subassemble */
786457de7509SStefano Zampini   if (multilevel_allowed) {
78651ae86dd6SStefano Zampini     Vec       vp[1];
78661ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
786757de7509SStefano Zampini     PetscBool reuse,reuser;
78681ae86dd6SStefano Zampini 
786957de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
787057de7509SStefano Zampini     else reuse = PETSC_FALSE;
787157de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
78721ae86dd6SStefano Zampini     vp[0] = NULL;
78731ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
78741ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
78751ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
78761ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
78771ae86dd6SStefano Zampini       nvecs = 1;
78781ae86dd6SStefano Zampini 
78791ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7880a198735bSStefano Zampini         Mat      B,loc_divudotp;
78811ae86dd6SStefano Zampini         Vec      v,p;
78821ae86dd6SStefano Zampini         IS       dummy;
78831ae86dd6SStefano Zampini         PetscInt np;
78841ae86dd6SStefano Zampini 
7885a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7886a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
78871ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
78887dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
78891ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
78901ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
78911ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
78921ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
78931ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
78941ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
78951ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
78961ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
78971ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
78981ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
78991ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
79001ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
790174e2c79eSStefano Zampini       }
79021ae86dd6SStefano Zampini     }
79031ae86dd6SStefano Zampini     if (reuser) {
79041e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
790574e2c79eSStefano Zampini     } else {
79061e0482f5SStefano 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);
79071ae86dd6SStefano Zampini     }
79081ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
79091ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
79101ae86dd6SStefano Zampini       PetscInt    nl;
79111ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
79121ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
79131ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
79141ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
79151ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
79161ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
79171ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
79181ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7919a198735bSStefano Zampini     } else {
7920a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
79211ae86dd6SStefano Zampini     }
79221ae86dd6SStefano Zampini   } else {
79231e0482f5SStefano 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);
79246e683305SStefano Zampini   }
792557de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
792657de7509SStefano Zampini     PetscMPIInt size;
7927f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
792857de7509SStefano Zampini     if (!multilevel_allowed) {
792957de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
79306e683305SStefano Zampini     } else {
793157de7509SStefano Zampini       Mat A;
7932779c1cceSStefano Zampini 
793357de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
793457de7509SStefano Zampini       if (coarse_mat_is) {
793557de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
793657de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
793757de7509SStefano Zampini         coarse_mat = coarse_mat_is;
793857de7509SStefano Zampini       }
793957de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
794057de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
794157de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7942779c1cceSStefano Zampini     }
7943779c1cceSStefano Zampini   }
794457de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
794557de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
79466e683305SStefano Zampini 
79476e683305SStefano Zampini   /* create local to global scatters for coarse problem */
794868457ee5SStefano Zampini   if (compute_vecs) {
79496e683305SStefano Zampini     PetscInt lrows;
79506e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
795157de7509SStefano Zampini     if (coarse_mat) {
795257de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
79536e683305SStefano Zampini     } else {
79546e683305SStefano Zampini       lrows = 0;
79556e683305SStefano Zampini     }
79566e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
79576e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
79586e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
79596e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
79606e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
79616e683305SStefano Zampini   }
79626e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7963c8587f34SStefano Zampini 
7964f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7965f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7966f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7967f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7968f9eb5b7dSStefano Zampini   } else {
7969f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7970f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7971c8587f34SStefano Zampini   }
7972c8587f34SStefano Zampini 
79736e683305SStefano Zampini   /* print some info if requested */
79746e683305SStefano Zampini   if (pcbddc->dbg_flag) {
79756e683305SStefano Zampini     if (!multilevel_allowed) {
79766e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
79776e683305SStefano Zampini       if (multilevel_requested) {
79786e683305SStefano 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);
79796e683305SStefano Zampini       } else if (pcbddc->max_levels) {
79806e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
79816e683305SStefano Zampini       }
79826e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
79836e683305SStefano Zampini     }
79846e683305SStefano Zampini   }
79856e683305SStefano Zampini 
79861e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
79871e0482f5SStefano Zampini   coarseG = NULL;
79881e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
79891e0482f5SStefano Zampini     MPI_Comm ccomm;
79901e0482f5SStefano Zampini     if (coarse_mat) {
79911e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
79921e0482f5SStefano Zampini     } else {
79931e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
79941e0482f5SStefano Zampini     }
79951e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
79961e0482f5SStefano Zampini   }
79971e0482f5SStefano Zampini 
7998f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
799957de7509SStefano Zampini   if (coarse_mat) {
80007274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
80016a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
80027274672aSStefano Zampini 
80036e683305SStefano Zampini     if (pcbddc->dbg_flag) {
800457de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
80056e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
80066e683305SStefano Zampini     }
8007f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8008312be037SStefano Zampini       char prefix[256],str_level[16];
8009e604994aSStefano Zampini       size_t len;
80101e0482f5SStefano Zampini 
801157de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8012422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8013c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8014f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
801557de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8016c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
80176e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8018c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
80191e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8020c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8021e604994aSStefano Zampini       /* prefix */
8022e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8023e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8024e604994aSStefano Zampini       if (!pcbddc->current_level) {
8025e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
8026e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
8027c8587f34SStefano Zampini       } else {
8028e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8029312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8030312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
803134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
803235529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8033e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
8034e604994aSStefano Zampini       }
8035e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
80363e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
80373e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
80383e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
80393e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8040f9eb5b7dSStefano Zampini       /* allow user customization */
8041f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
80423e3c6dadSStefano Zampini     }
80433e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
804451bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
80453e3c6dadSStefano Zampini     if (nisdofs) {
80463e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
80473e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
80483e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
80493e3c6dadSStefano Zampini       }
80503e3c6dadSStefano Zampini     }
80513e3c6dadSStefano Zampini     if (nisneu) {
80523e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
80533e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8054312be037SStefano Zampini     }
805530368db7SStefano Zampini     if (nisvert) {
805630368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
805730368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
805830368db7SStefano Zampini     }
80591e0482f5SStefano Zampini     if (coarseG) {
80601e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
80611e0482f5SStefano Zampini     }
8062f9eb5b7dSStefano Zampini 
8063f9eb5b7dSStefano Zampini     /* get some info after set from options */
8064f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8065b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8066b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8067f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8068f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
8069f9eb5b7dSStefano Zampini     }
8070b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
80717274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
80727274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
8073b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8074b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
8075b76f3995Sstefano_zampini     }
80767274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
80774f3a063dSStefano Zampini     if (isredundant) {
80784f3a063dSStefano Zampini       KSP inner_ksp;
80794f3a063dSStefano Zampini       PC  inner_pc;
80809326c5c6Sstefano_zampini 
80814f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
80824f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
80834f3a063dSStefano Zampini     }
8084f9eb5b7dSStefano Zampini 
808557de7509SStefano Zampini     /* parameters which miss an API */
80867274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
808757de7509SStefano Zampini     if (isbddc) {
8088720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
80897274672aSStefano Zampini 
8090720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
809157de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
809227b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
809327b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8094a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8095a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8096a198735bSStefano Zampini         IS                     row,col;
8097a198735bSStefano Zampini         const PetscInt         *gidxs;
8098a198735bSStefano Zampini         PetscInt               n,st,M,N;
8099a198735bSStefano Zampini 
8100a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8101a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8102a198735bSStefano Zampini         st   = st-n;
8103a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8104a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8105a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8106a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8107a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8108a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8109a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8110a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8111a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8112a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8113a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8114a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8115a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8116a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8117a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8118a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8119a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8120a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8121a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8122a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
81238ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8124a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8125720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8126bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8127720d30f9SStefano Zampini       }
8128d4d8cf7bSStefano Zampini     }
81299881197aSStefano Zampini 
81303301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
81315a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
81323301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
81333301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
81343301b35fSStefano Zampini     }
81353301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
81363301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
81373301b35fSStefano Zampini     }
81383301b35fSStefano Zampini     if (pc->pmat->spd_set) {
81393301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
81403301b35fSStefano Zampini     }
814127b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
814227b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
814327b6a85dSStefano Zampini     }
81446e683305SStefano Zampini     /* set operators */
81455f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
81466e683305SStefano Zampini     if (pcbddc->dbg_flag) {
81476e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
81486e683305SStefano Zampini     }
81496e683305SStefano Zampini   }
81501e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
81516e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8152b1ecc7b1SStefano Zampini #if 0
8153b9b85e73SStefano Zampini   {
8154b9b85e73SStefano Zampini     PetscViewer viewer;
8155b9b85e73SStefano Zampini     char filename[256];
8156b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8157b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
81586a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8159b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8160f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8161b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8162b9b85e73SStefano Zampini   }
8163b9b85e73SStefano Zampini #endif
8164f9eb5b7dSStefano Zampini 
816598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
816698a51de6SStefano Zampini     Vec crhs,csol;
816704708bb6SStefano Zampini 
8168f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8169f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8170f347579bSStefano Zampini     if (!csol) {
81712a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8172f9eb5b7dSStefano Zampini     }
8173f347579bSStefano Zampini     if (!crhs) {
81742a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8175f347579bSStefano Zampini     }
8176b0f5fe93SStefano Zampini   }
81771ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8178b0f5fe93SStefano Zampini 
8179b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8180b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8181b0f5fe93SStefano Zampini 
8182b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
81834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
81844f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
81854f1b2e48SStefano Zampini     }
8186b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8187b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8188b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8189b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8190b0f5fe93SStefano Zampini     if (coarse_mat) {
8191b0f5fe93SStefano Zampini       Vec         nullv;
8192b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8193b0f5fe93SStefano Zampini       PetscInt    nl;
8194b0f5fe93SStefano Zampini 
8195b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8196b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8197b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8198b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8199b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8200b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8201b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8202b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8203b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8204b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8205b0f5fe93SStefano Zampini     }
8206b0f5fe93SStefano Zampini   }
8207b0f5fe93SStefano Zampini 
8208b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8209b0f5fe93SStefano Zampini     PetscBool ispreonly;
8210b0f5fe93SStefano Zampini 
8211b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8212b0f5fe93SStefano Zampini       PetscBool isnull;
8213b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8214bef83e63SStefano Zampini       if (isnull) {
8215b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8216b0f5fe93SStefano Zampini       }
8217bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8218b0f5fe93SStefano Zampini     }
8219b0f5fe93SStefano Zampini     /* setup coarse ksp */
8220b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8221cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8222cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
82236e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8224c8587f34SStefano Zampini       KSP       check_ksp;
82252b510759SStefano Zampini       KSPType   check_ksp_type;
8226c8587f34SStefano Zampini       PC        check_pc;
82276e683305SStefano Zampini       Vec       check_vec,coarse_vec;
82286a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
82292b510759SStefano Zampini       PetscInt  its;
82306e683305SStefano Zampini       PetscBool compute_eigs;
82316e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
82326e683305SStefano Zampini       PetscInt  neigs;
82338e185a42SStefano Zampini       const char *prefix;
8234c8587f34SStefano Zampini 
82352b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
82366e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
8237422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
823823ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8239f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8240e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8241e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8242e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
82432b510759SStefano Zampini       if (ispreonly) {
82442b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
82456e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
82462b510759SStefano Zampini       } else {
8247cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
82486e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8249c8587f34SStefano Zampini       }
8250c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
82516e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
82526e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
82536e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8254a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8255a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8256a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8257a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8258c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8259c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8260c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8261c8587f34SStefano Zampini       /* create random vec */
82622701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8263c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
82646e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8265c8587f34SStefano Zampini       /* solve coarse problem */
82666e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8267cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
82686e683305SStefano Zampini       if (compute_eigs) {
8269854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8270854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
82716e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
82721ae86dd6SStefano Zampini         if (neigs) {
82736e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
82746e683305SStefano Zampini           lambda_min = eigs_r[0];
82756e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
82762701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
82772701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8278cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8279cbcc2c2aSStefano Zampini             }
8280c8587f34SStefano Zampini           }
8281c8587f34SStefano Zampini         }
82821ae86dd6SStefano Zampini       }
8283cbcc2c2aSStefano Zampini 
8284c8587f34SStefano Zampini       /* check coarse problem residual error */
82856e683305SStefano Zampini       if (pcbddc->dbg_flag) {
82866e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
82876e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
82886e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8289c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
82906e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
82916e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8292779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
82936e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
82946e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
82956e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
82966e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8297b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8298b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8299b0f5fe93SStefano Zampini         }
83006e683305SStefano Zampini         if (compute_eigs) {
83016e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8302b03ebc13SStefano Zampini           KSPConvergedReason reason;
8303deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8304c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8305b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
83066e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8307b03ebc13SStefano 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);
83086e683305SStefano Zampini           for (i=0;i<neigs;i++) {
83096e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8310c8587f34SStefano Zampini           }
83116e683305SStefano Zampini         }
83126e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
83136e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
83146e683305SStefano Zampini       }
8315e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
83162701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8317c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
83186e683305SStefano Zampini       if (compute_eigs) {
83196e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
83206e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8321c8587f34SStefano Zampini       }
83226e683305SStefano Zampini     }
83236e683305SStefano Zampini   }
8324bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8325cbcc2c2aSStefano Zampini   /* print additional info */
8326cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
83276e683305SStefano Zampini     /* waits until all processes reaches this point */
83286e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
8329cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
8330cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8331cbcc2c2aSStefano Zampini   }
8332cbcc2c2aSStefano Zampini 
83332b510759SStefano Zampini   /* free memory */
8334fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
8335c8587f34SStefano Zampini   PetscFunctionReturn(0);
8336c8587f34SStefano Zampini }
8337674ae819SStefano Zampini 
8338f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8339f34684f1SStefano Zampini {
8340f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8341f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8342f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8343dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8344dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
834573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8346dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8347f34684f1SStefano Zampini   PetscErrorCode ierr;
8348f34684f1SStefano Zampini 
8349f34684f1SStefano Zampini   PetscFunctionBegin;
8350f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
83516c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8352dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
83533bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8354dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8355dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
83566583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8357dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8358dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8359dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
83606c4ed002SBarry 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);
8361dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8362dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8363dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8364dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8365dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8366f34684f1SStefano Zampini 
8367f34684f1SStefano Zampini   /* check numbering */
8368f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8369019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8370dc456d91SStefano Zampini     PetscInt    i;
8371b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8372f34684f1SStefano Zampini 
8373f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8374f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8375f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
83761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8377019a44ceSStefano Zampini     /* counter */
8378019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8379019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8380019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8381019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8382019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8383019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8384f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8385f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8386727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8387f34684f1SStefano Zampini     }
8388f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8389f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8390f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8391e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8392e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8393e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8394e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8395f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8396019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8397f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8398019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
83992c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
840075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8401b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
84022c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
84032c66d082SStefano 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);
8404f34684f1SStefano Zampini       }
8405f34684f1SStefano Zampini     }
8406019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8407b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8408f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8409f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8410f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8411f34684f1SStefano Zampini     }
8412f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8413f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8414e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8415e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8416f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8417f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8418b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8419ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8420ca8b9ea9SStefano Zampini 
8421ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
84223bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8423f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8424f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8425f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8426f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
84274bc2dc4bSStefano 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);
8428f34684f1SStefano Zampini       }
8429f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8430ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8431f34684f1SStefano Zampini     }
8432f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
84331575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8434302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8435f34684f1SStefano Zampini   }
84368bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8437f34684f1SStefano Zampini   /* get back data */
8438f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8439f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8440674ae819SStefano Zampini   PetscFunctionReturn(0);
8441674ae819SStefano Zampini }
8442674ae819SStefano Zampini 
8443a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8444e456f2a8SStefano Zampini {
8445e456f2a8SStefano Zampini   IS             localis_t;
8446a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8447e456f2a8SStefano Zampini   PetscScalar    *vals;
8448e456f2a8SStefano Zampini   PetscErrorCode ierr;
8449e456f2a8SStefano Zampini 
8450e456f2a8SStefano Zampini   PetscFunctionBegin;
8451a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8452e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8453854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8454e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8455e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8456a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8457a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
84581035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
84593151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8460a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
84611035eff8SStefano Zampini   }
8462a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8463e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8464e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8465a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8466a7dc3881SStefano Zampini   /* now compute set in local ordering */
8467a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8468a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8469a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8470a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8471a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8472ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8473e456f2a8SStefano Zampini       lsize++;
8474e456f2a8SStefano Zampini     }
8475e456f2a8SStefano Zampini   }
8476854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8477a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8478ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8479e456f2a8SStefano Zampini       idxs[lsize++] = i;
8480e456f2a8SStefano Zampini     }
8481e456f2a8SStefano Zampini   }
8482a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8483a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8484e456f2a8SStefano Zampini   *localis = localis_t;
8485e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8486e456f2a8SStefano Zampini }
8487906d46d4SStefano Zampini 
848808122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8489b96c3477SStefano Zampini {
8490a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8491b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8492b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8493a64f4aa4SStefano Zampini   Mat                 S_j;
8494b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8495b96c3477SStefano Zampini   PetscBool           free_used_adj;
8496b96c3477SStefano Zampini   PetscErrorCode      ierr;
8497b96c3477SStefano Zampini 
8498b96c3477SStefano Zampini   PetscFunctionBegin;
8499b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8500b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
850108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8502b96c3477SStefano Zampini     used_xadj = NULL;
8503b96c3477SStefano Zampini     used_adjncy = NULL;
8504b96c3477SStefano Zampini   } else {
850508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
850608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
850708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
850808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8509b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8510b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8511b96c3477SStefano Zampini     } else {
85122fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8513b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8514b96c3477SStefano Zampini       PetscInt       nvtxs;
8515b96c3477SStefano Zampini 
85162fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
85172fffb893SStefano Zampini       if (flg_row) {
8518b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8519b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8520b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8521b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
85222fffb893SStefano Zampini       } else {
85232fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
85242fffb893SStefano Zampini         used_xadj = NULL;
85252fffb893SStefano Zampini         used_adjncy = NULL;
85262fffb893SStefano Zampini       }
85272fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8528b96c3477SStefano Zampini     }
8529b96c3477SStefano Zampini   }
8530d5574798SStefano Zampini 
8531d5574798SStefano Zampini   /* setup sub_schurs data */
8532a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8533df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8534df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8535a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
853691af6908SStefano 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);
8537a64f4aa4SStefano Zampini   } else {
853872b8c272SStefano Zampini     Mat       change = NULL;
85399d54b7f4SStefano Zampini     Vec       scaling = NULL;
8540111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8541111315fdSstefano_zampini     PetscInt  benign_n;
8542111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8543111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8544111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8545a3df083aSStefano Zampini 
85465feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
85475feab87aSStefano Zampini       PetscInt n_vertices;
85485feab87aSStefano Zampini 
85495feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
85502034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
85515feab87aSStefano Zampini     }
855204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
855304708bb6SStefano Zampini     if (!isseqaij) {
855404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
855504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
855604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
855704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
855804708bb6SStefano Zampini       } else {
8559511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
856004708bb6SStefano Zampini       }
856104708bb6SStefano Zampini     }
8562a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8563a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8564ca92afb2SStefano Zampini     } else {
8565a3df083aSStefano Zampini       benign_n = 0;
8566ca92afb2SStefano Zampini     }
8567b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8568b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8569b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
857072b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
857122db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8572b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
857322db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8574b7ab4a40SStefano Zampini     }
8575b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8576b7ab4a40SStefano 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 */
8577b7ab4a40SStefano Zampini     if (need_change) {
857888c03ad3SStefano Zampini       PC_IS   *pcisf;
857988c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
858088c03ad3SStefano Zampini       PC      pcf;
858188c03ad3SStefano Zampini 
8582e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
858388c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
858488c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
858588c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8586b9be95fcSstefano_zampini 
858788c03ad3SStefano Zampini       /* hacks */
858888c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
858972b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
859072b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
859172b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
859272b8c272SStefano Zampini       pcisf->n                     = pcis->n;
859372b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
859488c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
859588c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
859688c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
859788c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
859888c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
859988c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
860072b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
860188c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8602b9be95fcSstefano_zampini 
8603b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
860488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
860572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
860672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
860772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
860872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8609b9be95fcSstefano_zampini 
861088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
861172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
861288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
861388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
861488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
861588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
861688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
861788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8618b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
861988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
862088c03ad3SStefano Zampini     }
86219d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8622111315fdSstefano_zampini 
8623111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8624111315fdSstefano_zampini     if (iP) {
8625111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8626111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8627111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8628111315fdSstefano_zampini     }
8629111315fdSstefano_zampini     if (discrete_harmonic) {
8630111315fdSstefano_zampini       Mat A;
8631111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8632111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8633111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8634111315fdSstefano_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);
8635111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8636111315fdSstefano_zampini     } else {
863791af6908SStefano 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);
8638111315fdSstefano_zampini     }
863972b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
864072b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8641ca92afb2SStefano Zampini   }
8642d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8643b96c3477SStefano Zampini 
8644b96c3477SStefano Zampini   /* free adjacency */
8645b96c3477SStefano Zampini   if (free_used_adj) {
8646b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8647b96c3477SStefano Zampini   }
8648b96c3477SStefano Zampini   PetscFunctionReturn(0);
8649b96c3477SStefano Zampini }
8650b96c3477SStefano Zampini 
865108122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8652b96c3477SStefano Zampini {
8653b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8654b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8655b96c3477SStefano Zampini   PCBDDCGraph         graph;
8656b96c3477SStefano Zampini   PetscErrorCode      ierr;
8657b96c3477SStefano Zampini 
8658b96c3477SStefano Zampini   PetscFunctionBegin;
8659b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
866008122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
86613301b35fSStefano Zampini     IS       verticesIS,verticescomm;
86623301b35fSStefano Zampini     PetscInt vsize,*idxs;
8663b96c3477SStefano Zampini 
8664b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
86653301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
86663301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
86673301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
86683301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8669c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8670b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8671be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8672441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
86733301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8674b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8675b96c3477SStefano Zampini   } else {
8676b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8677b96c3477SStefano Zampini   }
8678e4d548c7SStefano Zampini   /* print some info */
86795c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8680e4d548c7SStefano Zampini     IS       vertices;
8681e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8682c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8683e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8684e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8685e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8686e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8687e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8688e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8689e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8690e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8691e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8692c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8693e4d548c7SStefano Zampini   }
8694b96c3477SStefano Zampini 
8695b96c3477SStefano Zampini   /* sub_schurs init */
8696b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8697b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8698b334f244SStefano Zampini   }
869988113c35SStefano 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);
8700a64f4aa4SStefano Zampini 
8701b96c3477SStefano Zampini   /* free graph struct */
870208122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8703b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8704b96c3477SStefano Zampini   }
8705b96c3477SStefano Zampini   PetscFunctionReturn(0);
8706b96c3477SStefano Zampini }
8707fa34dd3eSStefano Zampini 
8708fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8709fa34dd3eSStefano Zampini {
8710fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8711fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8712fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8713fa34dd3eSStefano Zampini 
8714fa34dd3eSStefano Zampini   PetscFunctionBegin;
8715fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8716fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
87174f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8718fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
87194f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
872075c01103SStefano Zampini     PetscReal      norm;
8721fa34dd3eSStefano Zampini     PetscInt       i;
8722fa34dd3eSStefano Zampini 
8723fa34dd3eSStefano Zampini     /* B0 and B0_B */
8724fa34dd3eSStefano Zampini     if (zerodiag) {
8725fa34dd3eSStefano Zampini       IS       dummy;
8726fa34dd3eSStefano Zampini 
87274f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
87287dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8729fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8730fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8731fa34dd3eSStefano Zampini     }
8732fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8733fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8734fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8735fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8736fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8737fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8738fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8739fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8740fa34dd3eSStefano Zampini     /* S_j */
8741fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8742fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8743fa34dd3eSStefano Zampini 
8744fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8745fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8746fa34dd3eSStefano Zampini     /* continuous in primal space */
8747fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8748fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8749fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8750fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
87514f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
87524f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8753fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8754fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8755fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8756fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8757fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8758fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8759fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8760fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8761fa34dd3eSStefano Zampini 
8762fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8763fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8764fa34dd3eSStefano Zampini     /* local with Schur */
8765fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8766fa34dd3eSStefano Zampini     if (zerodiag) {
8767fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
87684f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8769fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8770fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8771fa34dd3eSStefano Zampini     }
8772fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8773fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8774fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8775fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8776fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8777fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8778fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8779fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8780fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8781fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8782fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8783fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8784fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8785fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8786fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8787fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8788fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8789fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8790fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8791fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8792fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8793fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8794fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8795fa34dd3eSStefano Zampini     if (zerodiag) {
8796fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8797fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
87984f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8799fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8800fa34dd3eSStefano Zampini     }
8801fa34dd3eSStefano Zampini     /* BDDC */
8802fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8803fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8804fa34dd3eSStefano Zampini 
8805fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8806fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8807fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8808fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
88094f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
88104f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8811fa34dd3eSStefano Zampini     }
88124f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8813fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8814fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8815fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8816fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8817fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8818fa34dd3eSStefano Zampini   }
8819fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8820fa34dd3eSStefano Zampini }
88211e0482f5SStefano Zampini 
88221e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
88231e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
88241e0482f5SStefano Zampini {
88251e0482f5SStefano Zampini   Mat            At;
88261e0482f5SStefano Zampini   IS             rows;
88271e0482f5SStefano Zampini   PetscInt       rst,ren;
88281e0482f5SStefano Zampini   PetscErrorCode ierr;
88291e0482f5SStefano Zampini   PetscLayout    rmap;
88301e0482f5SStefano Zampini 
88311e0482f5SStefano Zampini   PetscFunctionBegin;
88321e0482f5SStefano Zampini   rst = ren = 0;
88331e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
88341e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
88351e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
88361e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
88371e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
88381e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
88391e0482f5SStefano Zampini   }
8840e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
88417dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
88421e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
88431e0482f5SStefano Zampini 
88441e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
88451e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
88461e0482f5SStefano Zampini     IS         from,to;
88471e0482f5SStefano Zampini     Vec        gvec;
88481e0482f5SStefano Zampini     PetscInt   lsize;
88491e0482f5SStefano Zampini 
88501e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
88511e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
88521e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
88531e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
88541e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
88551e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
88561e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
88571e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
88581e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
88591e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
88601e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
88611e0482f5SStefano Zampini     b->A = a->A;
88621e0482f5SStefano Zampini     b->B = a->B;
88631e0482f5SStefano Zampini 
88641e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
88651e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
88661e0482f5SStefano Zampini     b->rowindices      = 0;
88671e0482f5SStefano Zampini     b->rowvalues       = 0;
88681e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
88691e0482f5SStefano Zampini 
88701e0482f5SStefano Zampini     (*B)->rmap         = rmap;
88711e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
88721e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
88731e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
88741e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
88751e0482f5SStefano Zampini 
88761e0482f5SStefano Zampini     if (a->colmap) {
88771e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
88781e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
88791e0482f5SStefano Zampini #else
88801e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
88811e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
88821e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
88831e0482f5SStefano Zampini #endif
88841e0482f5SStefano Zampini     } else b->colmap = 0;
88851e0482f5SStefano Zampini     if (a->garray) {
88861e0482f5SStefano Zampini       PetscInt len;
88871e0482f5SStefano Zampini       len  = a->B->cmap->n;
88881e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
88891e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
88901e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
88911e0482f5SStefano Zampini     } else b->garray = 0;
88921e0482f5SStefano Zampini 
88931e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
88941e0482f5SStefano Zampini     b->lvec = a->lvec;
88951e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
88961e0482f5SStefano Zampini 
88971e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
88981e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
88991e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
89001e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
89011e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
89021e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
89031e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
89041e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
89051e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
89061e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
89071e0482f5SStefano Zampini   }
89081e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
89091e0482f5SStefano Zampini   PetscFunctionReturn(0);
89101e0482f5SStefano Zampini }
8911