xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b470e4b452d98f011eeb1f84a34fed34535fc656)
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);
68580bdb30SBarry Smith     ierr = PetscArraycpy(data,U+nr*i,(nr-i)*nr);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);
72580bdb30SBarry Smith     ierr = PetscArraycpy(data,U,i*nr);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;
1211683a169SBarry Smith     const PetscScalar *vals;
1221683a169SBarry Smith     PetscScalar       v;
1231e0482f5SStefano Zampini 
1247dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1261683a169SBarry Smith     ierr = MatDenseGetArrayRead(GEd,&vals);CHKERRQ(ierr);
127637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
128637e8532SStefano Zampini     v    = 1.;
1291e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1301e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1311683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(GEd,&vals);CHKERRQ(ierr);
1321e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1331e0482f5SStefano Zampini #if defined(PRINT_GDET)
1341e0482f5SStefano Zampini     {
1351e0482f5SStefano Zampini       PetscViewer viewer;
1361e0482f5SStefano Zampini       char filename[256];
1371e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1381e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1471e0482f5SStefano Zampini     }
1481e0482f5SStefano Zampini #endif
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1501e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1511e0482f5SStefano Zampini   }
1521e0482f5SStefano Zampini 
153a13144ffSStefano Zampini   PetscFunctionReturn(0);
154a13144ffSStefano Zampini }
155a13144ffSStefano Zampini 
156a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
157a13144ffSStefano Zampini {
158a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
159a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1600569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
161eee23b56SStefano Zampini   Vec                    tvec;
162a13144ffSStefano Zampini   PetscSF                sfv;
1631e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
164a13144ffSStefano Zampini   MPI_Comm               comm;
165c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
166c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1677d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
168a13144ffSStefano Zampini   PetscScalar            *vals,*work;
169a13144ffSStefano Zampini   PetscReal              *rwork;
170a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1711e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
172a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
173eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
174b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
175a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
176b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
177637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
178b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
179b03ebc13SStefano Zampini   PetscInt               *emarks;
180b03ebc13SStefano Zampini #endif
181213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
182a13144ffSStefano Zampini   PetscErrorCode         ierr;
183a13144ffSStefano Zampini 
184a13144ffSStefano Zampini   PetscFunctionBegin;
185213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
186213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
187213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
188213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
189213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
190213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
191213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
192213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
193a13144ffSStefano Zampini   print      = PETSC_FALSE;
194213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
195a13144ffSStefano Zampini 
196213b8bfaSStefano Zampini   /* Command line customization */
197213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
201213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
202213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
203213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
204213b8bfaSStefano Zampini 
205213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2061e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2071e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
209213b8bfaSStefano Zampini   if (!singular) {
210a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
211a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
212c2151214SStefano Zampini     for (i=0;i<n;i++) {
213a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
214a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
215a13144ffSStefano Zampini         break;
216a13144ffSStefano Zampini       }
217a13144ffSStefano Zampini     }
218a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
219a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
220a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
221213b8bfaSStefano Zampini   }
222a13144ffSStefano Zampini 
223213b8bfaSStefano Zampini   /* Get Nedelec field */
2246080607fSStefano 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 
236580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
237580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);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");
2586080607fSStefano 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) */
323580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
324580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
325c2151214SStefano Zampini   if (nedfieldlocal) {
326c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
328c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
329c2151214SStefano Zampini   } else {
330c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
331c2151214SStefano Zampini   }
332c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
334213b8bfaSStefano Zampini 
335213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
336213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
337213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     if (global) {
3391e0482f5SStefano Zampini       PetscInt rst;
3401e0482f5SStefano Zampini 
341c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
342c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
343c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
344c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
345c2151214SStefano Zampini         }
346c2151214SStefano Zampini       }
347a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
348c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3491e0482f5SStefano Zampini     } else {
3501e0482f5SStefano Zampini       PetscInt *tbz;
3511e0482f5SStefano Zampini 
3521e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3561e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3571e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3581e0482f5SStefano Zampini           tbz[cum++] = i;
3591e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3621e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3631e0482f5SStefano Zampini     }
364213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
365213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
366213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
367213b8bfaSStefano Zampini   }
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3727dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
378a13144ffSStefano Zampini 
379213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
380c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
387a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
388213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
389213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
390a13144ffSStefano Zampini 
3911e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
392213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
393a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
394213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
395a13144ffSStefano Zampini 
396213b8bfaSStefano Zampini   if (print) {
397213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
398213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
399213b8bfaSStefano Zampini   }
400213b8bfaSStefano Zampini 
401213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4020569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4030569b399SStefano Zampini 
404a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4054e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4064e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4107d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
411c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
412a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
413a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
414a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
415c2151214SStefano Zampini     IS is;
416c2151214SStefano Zampini 
417c2151214SStefano Zampini     if (fl2g) {
418c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
419c2151214SStefano Zampini     } else {
420c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
421c2151214SStefano Zampini     }
422c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
423c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
424a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
425a13144ffSStefano Zampini       if (idxs[i] >= 0) {
426a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4277d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
428a13144ffSStefano Zampini       }
429a13144ffSStefano Zampini     }
430c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
431c2151214SStefano Zampini     if (fl2g) {
432c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
433c2151214SStefano Zampini     }
434a13144ffSStefano Zampini   }
435a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
436c2151214SStefano Zampini     IS is;
437c2151214SStefano Zampini 
438c2151214SStefano Zampini     if (fl2g) {
439c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
440c2151214SStefano Zampini     } else {
441c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
442c2151214SStefano Zampini     }
443c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
444c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
445a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
446a13144ffSStefano Zampini       if (idxs[i] >= 0) {
447a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
448a13144ffSStefano Zampini       }
449a13144ffSStefano Zampini     }
450c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
451c2151214SStefano Zampini     if (fl2g) {
452c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
453a13144ffSStefano Zampini     }
454c2151214SStefano Zampini   }
455c2151214SStefano Zampini 
456213b8bfaSStefano Zampini   /* Count neighs per dof */
457b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
458b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini 
4607d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4617d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
46262b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
46362b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
464b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
46562b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
46662b0c6f7SStefano Zampini     }
46762b0c6f7SStefano Zampini   }
468637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
46962b0c6f7SStefano Zampini   if (!conforming) {
47062b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
47162b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
47262b0c6f7SStefano Zampini   }
4734e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
474dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
47562b0c6f7SStefano Zampini   cum  = 0;
476a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
477dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47862b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
479a13144ffSStefano Zampini       marks[cum++] = i;
480dec27d64SStefano Zampini       continue;
481dec27d64SStefano Zampini     }
482dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
48362b0c6f7SStefano Zampini     if (!conforming) {
48462b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
485a13144ffSStefano Zampini         marks[cum++] = i;
486a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
487a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
488a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
489a13144ffSStefano Zampini         }
49062b0c6f7SStefano Zampini       } else {
49162b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
49262b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
49362b0c6f7SStefano Zampini            - at most 2 endpoints
49462b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49562b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49662b0c6f7SStefano Zampini         */
49762b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49862b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49962b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
50062b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
50162b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
50262b0c6f7SStefano Zampini           if (nconn > order) ends++;
50362b0c6f7SStefano Zampini           else if (nconn == order) ints++;
50462b0c6f7SStefano Zampini           else undef++;
50562b0c6f7SStefano Zampini         }
50662b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50762b0c6f7SStefano Zampini           marks[cum++] = i;
50862b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
50962b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
51062b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini           }
51262b0c6f7SStefano Zampini         }
51362b0c6f7SStefano Zampini       }
514a13144ffSStefano Zampini     }
515dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
516dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
517dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
518dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
519a13144ffSStefano Zampini     }
520dec27d64SStefano Zampini   }
52162b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5234e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
52462b0c6f7SStefano Zampini   if (!conforming) {
52562b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52662b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
52762b0c6f7SStefano Zampini   }
5284e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
529637e8532SStefano Zampini 
530b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5314e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
532a13144ffSStefano Zampini   if (print) {
5334e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5344e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5354e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
536a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
537a13144ffSStefano Zampini   }
538a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
539dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
540a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
541637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5427d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
543b03ebc13SStefano Zampini     if (!order) { /* variable order */
544dec27d64SStefano Zampini       PetscReal vorder = 0.;
545dec27d64SStefano Zampini 
546dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
547dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
5486080607fSStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%D)",vorder,test);
549dec27d64SStefano Zampini       ord  = 1;
550dec27d64SStefano Zampini     }
551a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
5526080607fSStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %D connected with nodal dof %D with order %D",test,i,ord);
553a13144ffSStefano Zampini #endif
554637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5557d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5567d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5577d871cd7SStefano Zampini         break;
5587d871cd7SStefano Zampini       }
559637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
560637e8532SStefano Zampini         sneighs = PETSC_FALSE;
561637e8532SStefano Zampini       } else {
562637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
563637e8532SStefano Zampini         for (k=0;k<vc;k++) {
564637e8532SStefano Zampini           if (vn[k] != en[k]) {
565637e8532SStefano Zampini             sneighs = PETSC_FALSE;
566637e8532SStefano Zampini             break;
567637e8532SStefano Zampini           }
568637e8532SStefano Zampini         }
569637e8532SStefano Zampini       }
570637e8532SStefano Zampini     }
5717d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5726080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %D (%D %D %D)\n",i,!sneighs,test >= 3*ord,bdir);
573a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
574dec27d64SStefano Zampini     } else if (test == ord) {
575b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
5766080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %D\n",i);
577a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
578a13144ffSStefano Zampini       } else {
5796080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %D\n",i);
580a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
581a13144ffSStefano Zampini       }
582a13144ffSStefano Zampini     }
583a13144ffSStefano Zampini   }
584b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
585b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
5867d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
587b03ebc13SStefano Zampini 
588b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
589b03ebc13SStefano Zampini   if (order != 1) {
590b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
591b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
592b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
593b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
594b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
595b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
596b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
597b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
598b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
599b03ebc13SStefano Zampini             PetscInt v = jjt[k];
600b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
601b03ebc13SStefano Zampini               found = PETSC_TRUE;
602b03ebc13SStefano Zampini               break;
603b03ebc13SStefano Zampini             }
604b03ebc13SStefano Zampini           }
605b03ebc13SStefano Zampini         }
606b03ebc13SStefano Zampini         if (!found) {
6076080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D CLEARED\n",i);
608b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
609b03ebc13SStefano Zampini         } else {
6106080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D ACCEPTED\n",i);
611b03ebc13SStefano Zampini         }
612b03ebc13SStefano Zampini       }
613b03ebc13SStefano Zampini     }
614b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
615b03ebc13SStefano Zampini   }
616dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
617a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
618b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
619a13144ffSStefano Zampini 
620a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6210569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
622a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6234e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
624a13144ffSStefano Zampini 
6254e64d54eSstefano_zampini   /* Mark interior nodal dofs */
626a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6274e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
628a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
629a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6304e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
631a13144ffSStefano Zampini     }
632a13144ffSStefano Zampini   }
633a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
634a13144ffSStefano Zampini 
635a13144ffSStefano Zampini   /* communicate corners and splitpoints */
636a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
637580bdb30SBarry Smith   ierr = PetscArrayzero(sfvleaves,nv);CHKERRQ(ierr);
638580bdb30SBarry Smith   ierr = PetscArrayzero(sfvroots,Lv);CHKERRQ(ierr);
639a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
640a13144ffSStefano Zampini 
641a13144ffSStefano Zampini   if (print) {
642a13144ffSStefano Zampini     IS tbz;
643a13144ffSStefano Zampini 
644a13144ffSStefano Zampini     cum = 0;
645a13144ffSStefano Zampini     for (i=0;i<nv;i++)
646a13144ffSStefano Zampini       if (sfvleaves[i])
647a13144ffSStefano Zampini         vmarks[cum++] = i;
648a13144ffSStefano Zampini 
649a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
650a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
651a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
652a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
653a13144ffSStefano Zampini   }
654a13144ffSStefano Zampini 
655a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
656a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
657a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
658a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
659a13144ffSStefano Zampini 
6604e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6614e64d54eSstefano_zampini      and interior nodal dofs */
662a13144ffSStefano Zampini   cum = 0;
663a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
664a13144ffSStefano Zampini     if (sfvleaves[i]) {
665a13144ffSStefano Zampini       vmarks[cum++] = i;
666a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
667a13144ffSStefano Zampini     }
6684e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
669a13144ffSStefano Zampini   }
6704e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
671a13144ffSStefano Zampini   if (print) {
672a13144ffSStefano Zampini     IS tbz;
673a13144ffSStefano Zampini 
674a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6754e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
676a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
677a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
678a13144ffSStefano Zampini   }
679a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
680a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
681a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
682a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
683a13144ffSStefano Zampini 
684a13144ffSStefano Zampini   /* Recompute G */
685a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
686a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
687a13144ffSStefano Zampini   if (print) {
688a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
689a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
690a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
691a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
692a13144ffSStefano Zampini   }
693a13144ffSStefano Zampini 
694a13144ffSStefano Zampini   /* Get primal dofs (if any) */
695a13144ffSStefano Zampini   cum = 0;
696a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
697a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
698a13144ffSStefano Zampini   }
699c2151214SStefano Zampini   if (fl2g) {
700c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
701c2151214SStefano Zampini   }
702a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
703a13144ffSStefano Zampini   if (print) {
704a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
705a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
706a13144ffSStefano Zampini   }
707a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
708c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
709a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
710a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
711a13144ffSStefano Zampini 
712a13144ffSStefano Zampini   /* Compute edge connectivity */
713a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
715a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
716c2151214SStefano Zampini   if (fl2g) {
717c2151214SStefano Zampini     PetscBT   btf;
718c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
719c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
720c2151214SStefano Zampini 
721c2151214SStefano Zampini     /* create CSR for all local dofs */
722c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
723c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
7246080607fSStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %D. Should be %D",pcbddc->mat_graph->nvtxs_csr,n);
725c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
726c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
727c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
728c2151214SStefano Zampini       rest = PETSC_TRUE;
729c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
730c2151214SStefano Zampini     } else {
731c2151214SStefano Zampini       free   = PETSC_TRUE;
732c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
733c2151214SStefano Zampini       iiu[0] = 0;
734c2151214SStefano Zampini       for (i=0;i<n;i++) {
735c2151214SStefano Zampini         iiu[i+1] = i+1;
736c2151214SStefano Zampini         jju[i]   = -1;
737d904f53bSStefano Zampini       }
738c2151214SStefano Zampini     }
739c2151214SStefano Zampini 
740c2151214SStefano Zampini     /* import sizes of CSR */
741c2151214SStefano Zampini     iia[0] = 0;
742c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
743c2151214SStefano Zampini 
744c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
745c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
746c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
747c2151214SStefano Zampini     for (i=0;i<ne;i++) {
748c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
749c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
750c2151214SStefano Zampini     }
751c2151214SStefano Zampini 
752c2151214SStefano Zampini     /* iia in CSR */
753c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
754c2151214SStefano Zampini 
755c2151214SStefano Zampini     /* jja in CSR */
756c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
757c2151214SStefano Zampini     for (i=0;i<n;i++)
758c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
759c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
760c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
761c2151214SStefano Zampini 
762c2151214SStefano Zampini     /* map edge dofs connectivity */
7631e0482f5SStefano Zampini     if (jj) {
764c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
765c2151214SStefano Zampini       for (i=0;i<ne;i++) {
766c2151214SStefano Zampini         PetscInt e = idxs[i];
767c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
768c2151214SStefano Zampini       }
7691e0482f5SStefano Zampini     }
770c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
771c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
772c2151214SStefano Zampini     if (rest) {
773c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
774c2151214SStefano Zampini     }
775c2151214SStefano Zampini     if (free) {
776c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
777c2151214SStefano Zampini     }
778c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
779c2151214SStefano Zampini   } else {
780c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
781c2151214SStefano Zampini   }
782c2151214SStefano Zampini 
783a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
784a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
785213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
786a13144ffSStefano Zampini 
787a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
788c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
789a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
790a13144ffSStefano Zampini 
791c2151214SStefano Zampini   if (fl2g) {
792c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
793c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
794c2151214SStefano Zampini     for (i=0;i<nee;i++) {
795c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
796c2151214SStefano Zampini     }
797c2151214SStefano Zampini   } else {
798c2151214SStefano Zampini     eedges  = alleedges;
799c2151214SStefano Zampini     primals = allprimals;
800c2151214SStefano Zampini   }
801c2151214SStefano Zampini 
802a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
803580bdb30SBarry Smith   ierr = PetscArrayzero(marks,ne);CHKERRQ(ierr);
804c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
805c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
806c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
807c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
808c2151214SStefano Zampini   if (print) {
809c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
810c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
811c2151214SStefano Zampini   }
812c2151214SStefano Zampini 
813c2151214SStefano Zampini   maxsize = 0;
814a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
815a13144ffSStefano Zampini     PetscInt size,mark = i+1;
816a13144ffSStefano Zampini 
817a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
818a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
819a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
820a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
821a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
822a13144ffSStefano Zampini   }
823a13144ffSStefano Zampini 
824a13144ffSStefano Zampini   /* Find coarse edge endpoints */
825a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
826a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
827a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
828a13144ffSStefano Zampini     PetscInt mark = i+1,size;
829a13144ffSStefano Zampini 
830a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8311e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8326080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
833a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
834a13144ffSStefano Zampini     if (print) {
8356080607fSStefano Zampini       ierr = PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %D\n",i);CHKERRQ(ierr);
8366080607fSStefano Zampini       ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
837a13144ffSStefano Zampini     }
838a13144ffSStefano Zampini     for (j=0;j<size;j++) {
839a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
8406080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %D\n",ee);
841a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8426080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %D\n",jj[k]);
843a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
8446080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %D\n",jj[k]);
845a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
846a13144ffSStefano Zampini           PetscInt  k2;
847a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
848a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
8496080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %D: mark %D (ref mark %D), boundary %D\n",jjt[k2],marks[jjt[k2]],mark,!!PetscBTLookup(btb,jjt[k2]));
850c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
851c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
852c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
853a13144ffSStefano Zampini               corner = PETSC_TRUE;
854a13144ffSStefano Zampini               break;
855a13144ffSStefano Zampini             }
856a13144ffSStefano Zampini           }
857a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
8586080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %D\n",jj[k]);
859a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
860a13144ffSStefano Zampini           } else {
861a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
862a13144ffSStefano Zampini           }
863a13144ffSStefano Zampini         }
864a13144ffSStefano Zampini       }
865a13144ffSStefano Zampini     }
866a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
867a13144ffSStefano Zampini   }
868a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
869a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
870c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
871a13144ffSStefano Zampini 
872a13144ffSStefano Zampini   /* Reset marked primal dofs */
873a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
874a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
876a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini 
8780569b399SStefano Zampini   /* Now use the initial lG */
8790569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8800569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8810569b399SStefano Zampini   lG   = lGinit;
8820569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8830569b399SStefano Zampini 
884a13144ffSStefano Zampini   /* Compute extended cols indices */
885b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
886b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
887a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
888a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
889a13144ffSStefano Zampini   i   *= maxsize;
890b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
891a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
892a13144ffSStefano Zampini   eerr = PETSC_FALSE;
893a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
894b03ebc13SStefano Zampini     PetscInt size,found = 0;
895a13144ffSStefano Zampini 
896a13144ffSStefano Zampini     cum  = 0;
897a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8981e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8996080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
900a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
901b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
902a13144ffSStefano Zampini     for (j=0;j<size;j++) {
903a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
904b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
905b03ebc13SStefano Zampini         PetscInt vv = jj[k];
906b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
907b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
908b03ebc13SStefano Zampini       }
909a13144ffSStefano Zampini     }
910a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
911a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
912a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
913a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
914a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
915a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
916a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
917b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
918b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
919a13144ffSStefano Zampini       if (print) {
920a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
921a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
922a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
923a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
924a13144ffSStefano Zampini       }
925a13144ffSStefano Zampini       eerr = PETSC_TRUE;
926a13144ffSStefano Zampini     }
927a13144ffSStefano Zampini   }
9284e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
929a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
930a13144ffSStefano Zampini   if (done) {
931a13144ffSStefano Zampini     PetscInt *newprimals;
932a13144ffSStefano Zampini 
933a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
934a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
935a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
936580bdb30SBarry Smith     ierr = PetscArraycpy(newprimals,idxs,cum);CHKERRQ(ierr);
937a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9380569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
9396080607fSStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %D)\n",eerr);
940a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
941b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
942b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
943a13144ffSStefano Zampini         PetscInt size,mark = i+1;
944a13144ffSStefano Zampini 
945a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
946a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
947c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
948a13144ffSStefano Zampini         for (j=0;j<size;j++) {
949a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
9506080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %D [%D %D)\n",ee,ii[ee],ii[ee+1]);
951a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
952a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
953a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
954a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
955b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
9566080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %D\n",vv);
957a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
958a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
959a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
960a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
961a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
9626080607fSStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %D\n",ee2);
963a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
964a13144ffSStefano Zampini                   /* finally set the new corners */
965a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
9666080607fSStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %D\n",jj[k3]);
967a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
968a13144ffSStefano Zampini                   }
969a13144ffSStefano Zampini                 }
970a13144ffSStefano Zampini               }
971b03ebc13SStefano Zampini             } else {
9726080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %D\n",jj[k]);
973a13144ffSStefano Zampini             }
974a13144ffSStefano Zampini           }
975a13144ffSStefano Zampini         }
976b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
977b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
978b03ebc13SStefano Zampini 
979b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
9806080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %D\n",i);
981b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
982b03ebc13SStefano Zampini             PetscInt k2;
9836080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %D\n",jj[k]);
984b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
985b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
986b03ebc13SStefano Zampini           }
987b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
988b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
9896080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %D\n",idxs[j]);
990b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
991b03ebc13SStefano Zampini             }
992b03ebc13SStefano Zampini           }
993b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
994b03ebc13SStefano Zampini         }
995a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
996a13144ffSStefano Zampini       }
997a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
998a13144ffSStefano Zampini     }
999b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10000569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1001a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1002c2151214SStefano Zampini     if (fl2g) {
1003c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1004c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1005c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1006c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1007c2151214SStefano Zampini       }
1008c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1009c2151214SStefano Zampini     }
1010c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1011a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1012a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1013a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1014a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1015a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1016213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1017c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1018c2151214SStefano Zampini     if (fl2g) {
1019c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1020c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1021c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1022c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1023c2151214SStefano Zampini       }
1024c2151214SStefano Zampini     } else {
1025c2151214SStefano Zampini       eedges  = alleedges;
1026c2151214SStefano Zampini       primals = allprimals;
1027c2151214SStefano Zampini     }
1028b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1029a13144ffSStefano Zampini 
1030a13144ffSStefano Zampini     /* Mark again */
1031580bdb30SBarry Smith     ierr = PetscArrayzero(marks,ne);CHKERRQ(ierr);
1032a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1033a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1034a13144ffSStefano Zampini 
1035a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1036a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1037a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1038a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1039a13144ffSStefano Zampini     }
1040a13144ffSStefano Zampini     if (print) {
1041a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1042a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1043a13144ffSStefano Zampini     }
1044a13144ffSStefano Zampini 
1045a13144ffSStefano Zampini     /* Recompute extended cols */
1046a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1047a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1048a13144ffSStefano Zampini       PetscInt size;
1049a13144ffSStefano Zampini 
1050a13144ffSStefano Zampini       cum  = 0;
1051a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10521e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10536080607fSStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
1054a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1055a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1056a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10571e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1058a13144ffSStefano Zampini       }
1059a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1060a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1061a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1062a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1063a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1064a13144ffSStefano Zampini       if (cum != size -1) {
1065a13144ffSStefano Zampini         if (print) {
1066a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1067a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1068a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1069a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1070a13144ffSStefano Zampini         }
1071a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1072a13144ffSStefano Zampini       }
1073a13144ffSStefano Zampini     }
1074a13144ffSStefano Zampini   }
1075a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1076a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1077b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
10787d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1079a13144ffSStefano Zampini   /* an error should not occur at this point */
1080a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1081a13144ffSStefano Zampini 
10824e64d54eSstefano_zampini   /* Check the number of endpoints */
10830569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1084b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1085b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10864e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1087b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10884e64d54eSstefano_zampini 
1089b03ebc13SStefano Zampini     /* init with defaults */
1090b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10914e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10921e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10936080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
10944e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
10964e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10974e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10984e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10994e64d54eSstefano_zampini         PetscInt vv = jj[k];
11004e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
11016080607fSStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %D",i);
1102b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11034e64d54eSstefano_zampini         }
11044e64d54eSstefano_zampini       }
11054e64d54eSstefano_zampini     }
1106b03ebc13SStefano Zampini     if (found != 2) {
1107b03ebc13SStefano Zampini       PetscInt e;
1108b03ebc13SStefano Zampini       if (fl2g) {
1109b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1110b03ebc13SStefano Zampini       } else {
1111b03ebc13SStefano Zampini         e = idxs[0];
1112b03ebc13SStefano Zampini       }
11136080607fSStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %D corners for edge %D (astart %D, estart %D)",found,i,e,idxs[0]);
1114b03ebc13SStefano Zampini     }
1115eee23b56SStefano Zampini 
1116eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1117b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1118b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1119b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1120b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1121b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1122b03ebc13SStefano Zampini     }
1123eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11244e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
11256080607fSStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %D: ce %D, corners (%D,%D)\n",i,cedges[i],corners[2*i],corners[2*i+1]);
11264e64d54eSstefano_zampini   }
11270569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11284e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11294e64d54eSstefano_zampini 
1130a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1131a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1132a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1133a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1134a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1135a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1136a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1137a13144ffSStefano Zampini 
1138a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1139580bdb30SBarry Smith     ierr = PetscArrayzero(emarks,nee+1);CHKERRQ(ierr);
1140a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1141a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1142a13144ffSStefano Zampini       if (emax < emarks[j]) {
1143a13144ffSStefano Zampini         emax = emarks[j];
1144a13144ffSStefano Zampini         eemax = j;
1145a13144ffSStefano Zampini       }
1146a13144ffSStefano Zampini     }
1147a13144ffSStefano Zampini     /* not relevant for edges */
1148a13144ffSStefano Zampini     if (!eemax) continue;
1149a13144ffSStefano Zampini 
1150a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1151a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
11526080607fSStefano 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",marks[jj[j]]-1,eemax,i,jj[j]);
1153a13144ffSStefano Zampini       }
1154a13144ffSStefano Zampini     }
1155a13144ffSStefano Zampini   }
1156a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1157a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1158a13144ffSStefano Zampini #endif
1159a13144ffSStefano Zampini 
1160a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1161a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1162a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1163a13144ffSStefano Zampini   extmem *= maxsize;
1164a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1165a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1166a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1167a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1168a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1169213b8bfaSStefano Zampini 
1170a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1171a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1172a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1173a13144ffSStefano Zampini         mark = marks[jj[j]];
1174a13144ffSStefano Zampini 
1175a13144ffSStefano Zampini     /* not relevant */
1176a13144ffSStefano Zampini     if (!mark) continue;
1177a13144ffSStefano Zampini 
1178a13144ffSStefano Zampini     /* import extended row */
1179a13144ffSStefano Zampini     mark--;
1180a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1181a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
11826080607fSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %D > %D",extrowcum[mark] + size,extmem);
1183580bdb30SBarry Smith     ierr = PetscArraycpy(extrow+start,jj+ii[i],size);CHKERRQ(ierr);
1184a13144ffSStefano Zampini     extrowcum[mark] += size;
1185a13144ffSStefano Zampini   }
1186a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1187213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1188213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1189213b8bfaSStefano Zampini 
1190213b8bfaSStefano Zampini   /* Compress extrows */
1191a13144ffSStefano Zampini   cum  = 0;
1192a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1193a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1194a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1195a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1196a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1197a13144ffSStefano Zampini   }
1198a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1199a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1200a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1201a13144ffSStefano Zampini 
1202a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1203a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1204a13144ffSStefano Zampini 
1205a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1206a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1207c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1208c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1209a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1210a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1211a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12121e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1214a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1215213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1216a13144ffSStefano Zampini 
1217a13144ffSStefano Zampini   /* Defaults to identity */
1218c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1220a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1222a13144ffSStefano Zampini 
12231e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12241e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12251e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12261e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12271e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12281e0482f5SStefano Zampini     IS                     wis,gwis;
12291e0482f5SStefano Zampini     PetscInt               cnv,cne;
12301e0482f5SStefano Zampini 
12311e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12321e0482f5SStefano Zampini     if (fl2g) {
12331e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12341e0482f5SStefano Zampini     } else {
12351e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12361e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12371e0482f5SStefano Zampini     }
12381e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12391e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12401e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12411e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12421e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12431e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12441e0482f5SStefano Zampini 
12451e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12461e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12471e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12481e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12491e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12501e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12511e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12521e0482f5SStefano Zampini 
12531e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12541e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12551e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12561e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12571e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12581e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12591e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12601e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12611e0482f5SStefano Zampini   }
1262213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
12631e0482f5SStefano Zampini 
12641e0482f5SStefano Zampini #if defined(PRINT_GDET)
12651e0482f5SStefano Zampini   inc = 0;
12661e0482f5SStefano Zampini   lev = pcbddc->current_level;
12671e0482f5SStefano Zampini #endif
1268213b8bfaSStefano Zampini 
1269213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1270a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1271a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12721e0482f5SStefano Zampini     IS          cornersis = NULL;
12731e0482f5SStefano Zampini     PetscScalar cvals[2];
1274a13144ffSStefano Zampini 
12751e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12761e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12771e0482f5SStefano Zampini     }
12781e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1279a13144ffSStefano Zampini     if (Gins && GKins) {
12801683a169SBarry Smith       const PetscScalar *data;
1281a13144ffSStefano Zampini       const PetscInt    *rows,*cols;
1282a13144ffSStefano Zampini       PetscInt          nrh,nch,nrc,ncc;
1283a13144ffSStefano Zampini 
1284a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1285a13144ffSStefano Zampini       /* H1 */
1286a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1287a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
12881683a169SBarry Smith       ierr = MatDenseGetArrayRead(Gins,&data);CHKERRQ(ierr);
1289a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
12901683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(Gins,&data);CHKERRQ(ierr);
1291a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1292a13144ffSStefano Zampini       /* complement */
1293a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12946080607fSStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %D",i);
12956080607fSStefano 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);
12966080607fSStefano 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);
12971683a169SBarry Smith       ierr = MatDenseGetArrayRead(GKins,&data);CHKERRQ(ierr);
1298a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
12991683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(GKins,&data);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini       /* coarse discrete gradient */
13021e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13031e0482f5SStefano Zampini         PetscInt cols[2];
13041e0482f5SStefano Zampini 
13051e0482f5SStefano Zampini         cols[0] = 2*i;
13061e0482f5SStefano Zampini         cols[1] = 2*i+1;
13071e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13081e0482f5SStefano Zampini       }
1309a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1310a13144ffSStefano Zampini     }
1311a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1312a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1314a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1315a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1316a13144ffSStefano Zampini   }
1317213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1318a13144ffSStefano Zampini 
1319a13144ffSStefano Zampini   /* Start assembling */
1320a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13211e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13221e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13231e0482f5SStefano Zampini   }
1324a13144ffSStefano Zampini 
1325a13144ffSStefano Zampini   /* Free */
1326c2151214SStefano Zampini   if (fl2g) {
1327c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1328c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1329c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1330c2151214SStefano Zampini     }
1331c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1332c2151214SStefano Zampini   }
1333eee23b56SStefano Zampini 
1334eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1335eee23b56SStefano Zampini   {
1336eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1337eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1338eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1339eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1340eee23b56SStefano Zampini 
1341eee23b56SStefano Zampini     /* find first primal edge */
1342eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1343eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1344eee23b56SStefano Zampini     } else {
1345eee23b56SStefano Zampini       if (fl2g) {
1346eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1347eee23b56SStefano Zampini       }
1348eee23b56SStefano Zampini       idxs = cedges;
1349eee23b56SStefano Zampini     }
1350eee23b56SStefano Zampini     cum = 0;
1351eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1352eee23b56SStefano Zampini 
1353eee23b56SStefano Zampini     /* adapt connected components */
1354eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1355eee23b56SStefano Zampini     graph->cptr[0] = 0;
1356eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1357eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1358eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1359eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1360eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1361eee23b56SStefano Zampini         ncc++;
1362eee23b56SStefano Zampini         lc--;
1363eee23b56SStefano Zampini         cum++;
1364eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1365eee23b56SStefano Zampini       }
1366eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1367eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1368eee23b56SStefano Zampini       ncc++;
1369eee23b56SStefano Zampini     }
1370eee23b56SStefano Zampini     graph->ncc = ncc;
1371eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1372eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1373eee23b56SStefano Zampini     }
1374eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1375eee23b56SStefano Zampini   }
1376213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1377c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1378c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1379213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1380eee23b56SStefano Zampini 
1381c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1382a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1383a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1384b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1385b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1386a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1387a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1388a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1389a13144ffSStefano Zampini 
1390a13144ffSStefano Zampini   /* Complete assembling */
1391a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13921e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13931e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13941e0482f5SStefano Zampini #if 0
13951e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
13961e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
13971e0482f5SStefano Zampini #endif
13981e0482f5SStefano Zampini   }
1399a13144ffSStefano Zampini 
1400a13144ffSStefano Zampini   /* set change of basis */
1401213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1402a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1403a13144ffSStefano Zampini 
1404a13144ffSStefano Zampini   PetscFunctionReturn(0);
1405a13144ffSStefano Zampini }
1406a13144ffSStefano Zampini 
1407d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1408d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1409d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1410d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1411d8203eabSStefano Zampini {
1412d8203eabSStefano Zampini   PetscErrorCode ierr;
1413d8203eabSStefano Zampini   PetscInt       i;
1414d8203eabSStefano Zampini 
1415d8203eabSStefano Zampini   PetscFunctionBegin;
1416d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1417d8203eabSStefano Zampini     PetscInt first,last;
1418d8203eabSStefano Zampini 
1419d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
142086fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1421d8203eabSStefano Zampini     if (i>=first && i < last) {
1422d8203eabSStefano Zampini       PetscScalar *data;
1423d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1424d8203eabSStefano Zampini       if (!has_const) {
1425d8203eabSStefano Zampini         data[i-first] = 1.;
1426d8203eabSStefano Zampini       } else {
142786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1429d8203eabSStefano Zampini       }
1430d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1431d8203eabSStefano Zampini     }
1432d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1433d8203eabSStefano Zampini   }
1434d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1435d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1436d8203eabSStefano Zampini     PetscInt first,last;
14378860a134SJunchao Zhang     ierr = VecLockReadPop(quad_vecs[i]);CHKERRQ(ierr);
1438d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1439d8203eabSStefano Zampini     if (i>=first && i < last) {
1440d8203eabSStefano Zampini       PetscScalar *data;
1441d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1442d8203eabSStefano Zampini       if (!has_const) {
1443d8203eabSStefano Zampini         data[i-first] = 0.;
1444d8203eabSStefano Zampini       } else {
144586fa73c5SStefano Zampini         data[2*i-first] = 0.;
144686fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1447d8203eabSStefano Zampini       }
1448d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1449d8203eabSStefano Zampini     }
1450d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
14518860a134SJunchao Zhang     ierr = VecLockReadPush(quad_vecs[i]);CHKERRQ(ierr);
1452d8203eabSStefano Zampini   }
1453d8203eabSStefano Zampini   PetscFunctionReturn(0);
1454d8203eabSStefano Zampini }
1455d8203eabSStefano Zampini 
14568ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1457669cc0f4SStefano Zampini {
1458a198735bSStefano Zampini   Mat                    loc_divudotp;
1459fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14608ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1461669cc0f4SStefano Zampini   PetscScalar            *vals;
1462669cc0f4SStefano Zampini   const PetscScalar      *array;
14630f27d399SStefano Zampini   PetscInt               i,maxneighs,maxsize,*gidxs;
1464a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14651ae86dd6SStefano Zampini   PetscMPIInt            rank;
1466a198735bSStefano Zampini   PetscErrorCode         ierr;
1467669cc0f4SStefano Zampini 
1468669cc0f4SStefano Zampini   PetscFunctionBegin;
1469a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1470a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
14718037d520SStefano Zampini   if (!maxneighs) {
14728037d520SStefano Zampini     ierr  = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14738037d520SStefano Zampini     *nnsp = NULL;
14748037d520SStefano Zampini     PetscFunctionReturn(0);
1475669cc0f4SStefano Zampini   }
1476669cc0f4SStefano Zampini   maxsize = 0;
1477a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
14780f27d399SStefano Zampini   ierr = PetscMalloc2(maxsize,&gidxs,maxsize,&vals);CHKERRQ(ierr);
1479669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1480669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14818ae0ca82SStefano Zampini   if (!transpose) {
14828ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14838ae0ca82SStefano Zampini   } else {
14848ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14858ae0ca82SStefano Zampini   }
1486669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14871ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1488d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1489669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
14908860a134SJunchao Zhang     ierr = VecLockReadPop(quad_vecs[i]);CHKERRQ(ierr);
1491669cc0f4SStefano Zampini   }
1492d8203eabSStefano Zampini 
1493669cc0f4SStefano Zampini   /* compute local quad vec */
1494a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
14958ae0ca82SStefano Zampini   if (!transpose) {
1496a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
14978ae0ca82SStefano Zampini   } else {
14988ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
14998ae0ca82SStefano Zampini   }
1500669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15018ae0ca82SStefano Zampini   if (!transpose) {
1502a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15038ae0ca82SStefano Zampini   } else {
15048ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15058ae0ca82SStefano Zampini   }
1506fa23a32eSStefano Zampini   if (vl2l) {
1507187c917aSStefano Zampini     Mat        lA;
1508187c917aSStefano Zampini     VecScatter sc;
1509187c917aSStefano Zampini 
1510187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1511187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
15129448b7f1SJunchao Zhang     ierr = VecScatterCreate(v,NULL,vins,vl2l,&sc);CHKERRQ(ierr);
1513187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1514187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1515187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1516fa23a32eSStefano Zampini   } else {
1517fa23a32eSStefano Zampini     vins = v;
1518fa23a32eSStefano Zampini   }
1519fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1520669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15219a962809SStefano Zampini 
15221ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15231ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1524a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) {
1525669cc0f4SStefano Zampini     const PetscInt    *idxs;
1526669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1527669cc0f4SStefano Zampini 
1528a040e873SStefano Zampini     idxs = shared[i];
1529a040e873SStefano Zampini     nn   = n_shared[i];
1530669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15311ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1532669cc0f4SStefano Zampini     idx  = -(idx+1);
15330f27d399SStefano Zampini     ierr = ISLocalToGlobalMappingApply(map,nn,idxs,gidxs);CHKERRQ(ierr);
15340f27d399SStefano Zampini     ierr = VecSetValues(quad_vecs[idx],nn,gidxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1535669cc0f4SStefano Zampini   }
1536a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1537fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1538fa23a32eSStefano Zampini   if (vl2l) {
1539187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1540fa23a32eSStefano Zampini   }
1541669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
15420f27d399SStefano Zampini   ierr = PetscFree2(gidxs,vals);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini 
1544669cc0f4SStefano Zampini   /* assemble near null space */
1545669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1546669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1547669cc0f4SStefano Zampini   }
1548669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1549669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
15503272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
15518860a134SJunchao Zhang     ierr = VecLockReadPush(quad_vecs[i]);CHKERRQ(ierr);
1552669cc0f4SStefano Zampini   }
1553669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1554669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1555669cc0f4SStefano Zampini }
1556669cc0f4SStefano Zampini 
15577620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15587620a527SStefano Zampini {
15597620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15607620a527SStefano Zampini   PetscErrorCode ierr;
15617620a527SStefano Zampini 
15627620a527SStefano Zampini   PetscFunctionBegin;
15637620a527SStefano Zampini   if (primalv) {
15647620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15657620a527SStefano Zampini       IS list[2], newp;
15667620a527SStefano Zampini 
15677620a527SStefano Zampini       list[0] = primalv;
15687620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15697620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
15707620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
15717620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
15727620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15737620a527SStefano Zampini     } else {
15747620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
15757620a527SStefano Zampini     }
15767620a527SStefano Zampini   }
15777620a527SStefano Zampini   PetscFunctionReturn(0);
15787620a527SStefano Zampini }
1579669cc0f4SStefano Zampini 
15801c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15811c7a958bSStefano Zampini {
15821c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15831c7a958bSStefano Zampini 
15841c7a958bSStefano Zampini   PetscFunctionBegin;
15851c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15861c7a958bSStefano Zampini   PetscFunctionReturn(0);
15871c7a958bSStefano Zampini }
1588674ae819SStefano Zampini 
15891f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15901f4df5f7SStefano Zampini {
15911f4df5f7SStefano Zampini   PetscErrorCode ierr;
15921f4df5f7SStefano Zampini   Vec            local,global;
15931f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15941f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15955c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15961f4df5f7SStefano Zampini 
15971f4df5f7SStefano Zampini   PetscFunctionBegin;
15985c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
15995c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16005c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16011f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
160221ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16031f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
1604*b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(global,PETSC_TRUE);CHKERRQ(ierr);
1605*b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(local,PETSC_TRUE);CHKERRQ(ierr);
16066a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16076a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16086a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16096a8fc67bSStefano Zampini     }
16106a8fc67bSStefano Zampini     goto boundary;
16116a8fc67bSStefano Zampini   }
16125c5e10d6SStefano Zampini 
16131f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16141f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16151f4df5f7SStefano Zampini       PetscInt i;
16160c85b387SStefano Zampini 
16171f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16181f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16190c85b387SStefano Zampini         PetscInt bs;
16200c85b387SStefano Zampini 
16211f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16220c85b387SStefano Zampini         ierr = ISGetBlockSize(pcbddc->ISForDofs[i],&bs);CHKERRQ(ierr);
16230c85b387SStefano Zampini         ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
16241f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16251f4df5f7SStefano Zampini       }
16261f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16271f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16281f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16291f4df5f7SStefano Zampini     }
16301f4df5f7SStefano Zampini   } else {
163121ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
163221ef3d20SStefano Zampini       DM dm;
163321ef3d20SStefano Zampini 
163421ef3d20SStefano Zampini       ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
16354f819b78SStefano Zampini       if (!dm) {
16364f819b78SStefano Zampini         ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
163721ef3d20SStefano Zampini       }
163821ef3d20SStefano Zampini       if (dm) {
163921ef3d20SStefano Zampini         IS      *fields;
164021ef3d20SStefano Zampini         PetscInt nf,i;
16410c85b387SStefano Zampini 
164221ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
164321ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
164421ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16450c85b387SStefano Zampini           PetscInt bs;
16460c85b387SStefano Zampini 
164721ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16480c85b387SStefano Zampini           ierr = ISGetBlockSize(fields[i],&bs);CHKERRQ(ierr);
16490c85b387SStefano Zampini           ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
165021ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
165121ef3d20SStefano Zampini         }
165221ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
165321ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
165421ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
165521ef3d20SStefano Zampini         PetscContainer   c;
165621ef3d20SStefano Zampini 
165721ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
165821ef3d20SStefano Zampini         if (c) {
165921ef3d20SStefano Zampini           MatISLocalFields lf;
166021ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
166121ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
166221ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16631f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1664986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
166521ef3d20SStefano Zampini           if (i > 1) {
1666986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16671f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16681f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16691f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16701f4df5f7SStefano Zampini             }
16711f4df5f7SStefano Zampini           }
167221ef3d20SStefano Zampini         }
167321ef3d20SStefano Zampini       }
16747a0e7b2cSstefano_zampini     } else {
16757a0e7b2cSstefano_zampini       PetscInt i;
16767a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16777a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16787a0e7b2cSstefano_zampini       }
16791f4df5f7SStefano Zampini     }
1680986cdee1SStefano Zampini   }
16811f4df5f7SStefano Zampini 
16825c5e10d6SStefano Zampini boundary:
16831f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16841f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16857a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16867a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16871f4df5f7SStefano Zampini   }
16881f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16891f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16907a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16917a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16921f4df5f7SStefano Zampini   }
16931f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16941f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16951f4df5f7SStefano Zampini   }
16961f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16971f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16987620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16997620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
17007620a527SStefano Zampini     IS        primalv = NULL;
17017620a527SStefano Zampini     PetscInt  i;
17028361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
17037a0e7b2cSstefano_zampini 
17047620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17057620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17067620a527SStefano Zampini     }
17077620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17088361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17097620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17107620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17117620a527SStefano Zampini   }
17127620a527SStefano Zampini   /* early stage corner detection */
17137620a527SStefano Zampini   {
17147620a527SStefano Zampini     DM dm;
17157620a527SStefano Zampini 
17167620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17174f819b78SStefano Zampini     if (!dm) {
17184f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17194f819b78SStefano Zampini     }
17207620a527SStefano Zampini     if (dm) {
17217620a527SStefano Zampini       PetscBool isda;
17227620a527SStefano Zampini 
17237620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17247620a527SStefano Zampini       if (isda) {
17257620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17267620a527SStefano Zampini         IS                     corners;
17277620a527SStefano Zampini         Mat                    lA;
17284f819b78SStefano Zampini         PetscBool              gl,lo;
17297620a527SStefano Zampini 
17304f819b78SStefano Zampini         {
17314f819b78SStefano Zampini           Vec               cvec;
17324f819b78SStefano Zampini           const PetscScalar *coords;
17334f819b78SStefano Zampini           PetscInt          dof,n,cdim;
17344f819b78SStefano Zampini           PetscBool         memc = PETSC_TRUE;
17354f819b78SStefano Zampini 
17364f819b78SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17374f819b78SStefano Zampini           ierr = DMGetCoordinates(dm,&cvec);CHKERRQ(ierr);
17384f819b78SStefano Zampini           ierr = VecGetLocalSize(cvec,&n);CHKERRQ(ierr);
17394f819b78SStefano Zampini           ierr = VecGetBlockSize(cvec,&cdim);CHKERRQ(ierr);
17404f819b78SStefano Zampini           n   /= cdim;
17414f819b78SStefano Zampini           ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
17424f819b78SStefano Zampini           ierr = PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords);CHKERRQ(ierr);
17434f819b78SStefano Zampini           ierr = VecGetArrayRead(cvec,&coords);CHKERRQ(ierr);
17444f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17454f819b78SStefano Zampini           memc = PETSC_FALSE;
17464f819b78SStefano Zampini #endif
17474f819b78SStefano Zampini           if (dof != 1) memc = PETSC_FALSE;
17484f819b78SStefano Zampini           if (memc) {
1749580bdb30SBarry Smith             ierr = PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof);CHKERRQ(ierr);
17504f819b78SStefano Zampini           } else { /* BDDC graph does not use any blocked information, we need to replicate the data */
17514f819b78SStefano Zampini             PetscReal *bcoords = pcbddc->mat_graph->coords;
17524f819b78SStefano Zampini             PetscInt  i, b, d;
17534f819b78SStefano Zampini 
17544f819b78SStefano Zampini             for (i=0;i<n;i++) {
17554f819b78SStefano Zampini               for (b=0;b<dof;b++) {
17564f819b78SStefano Zampini                 for (d=0;d<cdim;d++) {
17574f819b78SStefano Zampini                   bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]);
17584f819b78SStefano Zampini                 }
17594f819b78SStefano Zampini               }
17604f819b78SStefano Zampini             }
17614f819b78SStefano Zampini           }
17624f819b78SStefano Zampini           ierr = VecRestoreArrayRead(cvec,&coords);CHKERRQ(ierr);
17634f819b78SStefano Zampini           pcbddc->mat_graph->cdim  = cdim;
17644f819b78SStefano Zampini           pcbddc->mat_graph->cnloc = dof*n;
17654f819b78SStefano Zampini           pcbddc->mat_graph->cloc  = PETSC_FALSE;
17664f819b78SStefano Zampini         }
1767d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17687620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17697620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17707620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17714f819b78SStefano Zampini         lo   = (PetscBool)(l2l && corners);
17724f819b78SStefano Zampini         ierr = MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
17734f819b78SStefano Zampini         if (gl) { /* From PETSc's DMDA */
17747620a527SStefano Zampini           const PetscInt    *idx;
177572ed36d8SStefano Zampini           PetscInt          dof,bs,*idxout,n;
17767620a527SStefano Zampini 
177772ed36d8SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17787620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17797620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17807620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
178172ed36d8SStefano Zampini           if (bs == dof) {
17827620a527SStefano Zampini             ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17837620a527SStefano Zampini             ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
178472ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
178572ed36d8SStefano Zampini             PetscInt i,d;
178672ed36d8SStefano Zampini 
178772ed36d8SStefano Zampini             ierr = PetscMalloc1(dof*n,&idxout);CHKERRQ(ierr);
178872ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
178972ed36d8SStefano Zampini             ierr = ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout);CHKERRQ(ierr);
179072ed36d8SStefano Zampini 
179172ed36d8SStefano Zampini             bs = 1;
179272ed36d8SStefano Zampini             n *= dof;
179372ed36d8SStefano Zampini           }
17947620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1795d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17967620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17977620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17987620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17991c7a958bSStefano Zampini           pcbddc->corner_selected  = PETSC_TRUE;
18004f819b78SStefano Zampini           pcbddc->corner_selection = PETSC_TRUE;
18014f819b78SStefano Zampini         }
18024f819b78SStefano Zampini         if (corners) {
1803d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
18047620a527SStefano Zampini         }
18057620a527SStefano Zampini       }
18067620a527SStefano Zampini     }
18077620a527SStefano Zampini   }
18081c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
18091c7a958bSStefano Zampini     DM dm;
18101c7a958bSStefano Zampini 
18111c7a958bSStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
18124f819b78SStefano Zampini     if (!dm) {
18134f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
18141c7a958bSStefano Zampini     }
18154f819b78SStefano Zampini     if (dm) { /* this can get very expensive, I need to find a faster alternative */
18161c7a958bSStefano Zampini       Vec            vcoords;
18171c7a958bSStefano Zampini       PetscSection   section;
18181c7a958bSStefano Zampini       PetscReal      *coords;
18191c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
18201c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
18211c7a958bSStefano Zampini 
18221c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
182392fd8e1eSJed Brown       ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
18241c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
18251c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
18261c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
18271c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
18281c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
18291c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
18301c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
18311c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
18321c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
18331c7a958bSStefano Zampini         PetscInt          i;
18341c7a958bSStefano Zampini         const PetscScalar *v;
18351c7a958bSStefano Zampini 
18361c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
18371c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
18381c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
18391c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
18401c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
18411c7a958bSStefano Zampini       }
18421c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
18431c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
18441c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
18451c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
18461c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
18471c7a958bSStefano Zampini     }
18481c7a958bSStefano Zampini   }
18497a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18507a0e7b2cSstefano_zampini }
18517a0e7b2cSstefano_zampini 
18527a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18537a0e7b2cSstefano_zampini {
18547a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18557a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
18567a0e7b2cSstefano_zampini   IS              nis;
18577a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18587a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18597a0e7b2cSstefano_zampini   PetscBool       *ld;
18607a0e7b2cSstefano_zampini 
18617a0e7b2cSstefano_zampini   PetscFunctionBegin;
18627a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18637a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18647a0e7b2cSstefano_zampini     /* init rootdata with true */
18657a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
18667a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
18677a0e7b2cSstefano_zampini   } else {
1868580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
18697a0e7b2cSstefano_zampini   }
1870580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
18717a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18727a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18737a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18747a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18757a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18767a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18777a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18787a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18797a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18807a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18817a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18827a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18837a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18847a0e7b2cSstefano_zampini   } else {
18857a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18867a0e7b2cSstefano_zampini   }
18877a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18887a0e7b2cSstefano_zampini     if (ld[i])
18897a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18907a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18917a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18927a0e7b2cSstefano_zampini   *is  = nis;
18931f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18941f4df5f7SStefano Zampini }
18951f4df5f7SStefano Zampini 
18963e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18973e589ea0SStefano Zampini {
18983e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18993e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
19003e589ea0SStefano Zampini   PetscErrorCode    ierr;
19013e589ea0SStefano Zampini 
19023e589ea0SStefano Zampini   PetscFunctionBegin;
19033e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
19043e589ea0SStefano Zampini     PetscFunctionReturn(0);
19053e589ea0SStefano Zampini   }
19063e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19073e589ea0SStefano Zampini     Vec swap;
19083e589ea0SStefano Zampini 
19093e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19103e589ea0SStefano Zampini     swap = pcbddc->work_change;
19113e589ea0SStefano Zampini     pcbddc->work_change = r;
19123e589ea0SStefano Zampini     r = swap;
19133e589ea0SStefano Zampini   }
19143e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19153e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19163e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1917c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19183e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
19193e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19203e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19213e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1922f913dca9SStefano Zampini     pcbddc->work_change = r;
19233e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19243e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19253e589ea0SStefano Zampini   }
19263e589ea0SStefano Zampini   PetscFunctionReturn(0);
19273e589ea0SStefano Zampini }
19283e589ea0SStefano Zampini 
1929a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1930a3df083aSStefano Zampini {
1931a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1932a3df083aSStefano Zampini   PetscErrorCode          ierr;
1933a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1934a3df083aSStefano Zampini 
1935a3df083aSStefano Zampini   PetscFunctionBegin;
1936a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1937a3df083aSStefano Zampini   if (transpose) {
1938a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1939a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1940a3df083aSStefano Zampini   } else {
1941a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1942a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1943a3df083aSStefano Zampini   }
1944a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1945a3df083aSStefano Zampini   if (apply_right) {
1946a3df083aSStefano Zampini     const PetscScalar *ax;
1947a3df083aSStefano Zampini     PetscInt          nl,i;
1948a3df083aSStefano Zampini 
1949a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1950a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1951580bdb30SBarry Smith     ierr = PetscArraycpy(ctx->work,ax,nl);CHKERRQ(ierr);
1952a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1953a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1954a3df083aSStefano Zampini       PetscScalar    sum,val;
1955a3df083aSStefano Zampini       const PetscInt *idxs;
1956a3df083aSStefano Zampini       PetscInt       nz,j;
1957a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1958a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1959a3df083aSStefano Zampini       sum = 0.;
1960a3df083aSStefano Zampini       if (ctx->apply_p0) {
1961a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1962a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1963a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1964a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1965a3df083aSStefano Zampini         }
1966a3df083aSStefano Zampini       } else {
1967a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1968a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1969a3df083aSStefano Zampini         }
1970a3df083aSStefano Zampini       }
1971a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1972a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1973a3df083aSStefano Zampini     }
1974a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1975a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1976a3df083aSStefano Zampini   }
1977a3df083aSStefano Zampini   if (transpose) {
1978a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1979a3df083aSStefano Zampini   } else {
1980a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1981a3df083aSStefano Zampini   }
1982a3df083aSStefano Zampini   if (reset_x) {
1983a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1984a3df083aSStefano Zampini   }
1985a3df083aSStefano Zampini   if (apply_left) {
1986a3df083aSStefano Zampini     PetscScalar *ay;
1987a3df083aSStefano Zampini     PetscInt    i;
1988a3df083aSStefano Zampini 
1989a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1990a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1991a3df083aSStefano Zampini       PetscScalar    sum,val;
1992a3df083aSStefano Zampini       const PetscInt *idxs;
1993a3df083aSStefano Zampini       PetscInt       nz,j;
1994a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1995a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1996a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1997a3df083aSStefano Zampini       if (ctx->apply_p0) {
1998a3df083aSStefano Zampini         sum = 0.;
1999a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2000a3df083aSStefano Zampini           sum += ay[idxs[j]];
2001a3df083aSStefano Zampini           ay[idxs[j]] += val;
2002a3df083aSStefano Zampini         }
2003a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
2004a3df083aSStefano Zampini       } else {
2005a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2006a3df083aSStefano Zampini           ay[idxs[j]] += val;
2007a3df083aSStefano Zampini         }
2008a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
2009a3df083aSStefano Zampini       }
2010a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
2011a3df083aSStefano Zampini     }
2012a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
2013a3df083aSStefano Zampini   }
2014a3df083aSStefano Zampini   PetscFunctionReturn(0);
2015a3df083aSStefano Zampini }
2016a3df083aSStefano Zampini 
2017a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
2018a3df083aSStefano Zampini {
2019a3df083aSStefano Zampini   PetscErrorCode ierr;
2020a3df083aSStefano Zampini 
2021a3df083aSStefano Zampini   PetscFunctionBegin;
2022a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
2023a3df083aSStefano Zampini   PetscFunctionReturn(0);
2024a3df083aSStefano Zampini }
2025a3df083aSStefano Zampini 
2026a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
2027a3df083aSStefano Zampini {
2028a3df083aSStefano Zampini   PetscErrorCode ierr;
2029a3df083aSStefano Zampini 
2030a3df083aSStefano Zampini   PetscFunctionBegin;
2031a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
2032a3df083aSStefano Zampini   PetscFunctionReturn(0);
2033a3df083aSStefano Zampini }
2034a3df083aSStefano Zampini 
2035a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
2036a3df083aSStefano Zampini {
2037a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
2038a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
2039a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
2040a3df083aSStefano Zampini   PetscErrorCode          ierr;
2041a3df083aSStefano Zampini 
2042a3df083aSStefano Zampini   PetscFunctionBegin;
2043a3df083aSStefano Zampini   if (!restore) {
20441dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2045a3df083aSStefano Zampini     PetscScalar        *work;
2046b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2047a3df083aSStefano Zampini 
20489a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20499a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
2050a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
2051a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
2052a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2053a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
2054a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
2055a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
2056a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2057a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2058a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2059a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2060a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2061a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2062059032f7SStefano Zampini     if (reuse) {
2063a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20641dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2065059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2066059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2067059032f7SStefano Zampini       PetscInt               i;
2068059032f7SStefano Zampini 
2069059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2070059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2071059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2072059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2073059032f7SStefano Zampini       }
2074059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20751dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2076059032f7SStefano Zampini     }
2077a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2078a3df083aSStefano Zampini     ctx->work = work;
2079a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2080a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2081a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2082a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2083a3df083aSStefano Zampini 
2084a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2085a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2086a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2087a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2088a3df083aSStefano Zampini   } else {
20891dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20901dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20911dd7afcfSStefano Zampini     }
2092a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2093a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2094a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20951dd7afcfSStefano Zampini     ctx->A = NULL;
20961dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20971dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20981dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20991dd7afcfSStefano Zampini     if (ctx->free) {
2100059032f7SStefano Zampini       PetscInt i;
21011dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2102059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2103059032f7SStefano Zampini       }
2104059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2105059032f7SStefano Zampini     }
2106a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2107a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2108a3df083aSStefano Zampini   }
2109a3df083aSStefano Zampini   PetscFunctionReturn(0);
2110a3df083aSStefano Zampini }
2111a3df083aSStefano Zampini 
2112a3df083aSStefano Zampini /* used just in bddc debug mode */
2113a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2114a3df083aSStefano Zampini {
2115a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2116a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2117a3df083aSStefano Zampini   Mat            An;
2118a3df083aSStefano Zampini   PetscErrorCode ierr;
2119a3df083aSStefano Zampini 
2120a3df083aSStefano Zampini   PetscFunctionBegin;
2121a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2122a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2123a3df083aSStefano Zampini   if (is1) {
21247dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2125a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2126a3df083aSStefano Zampini   } else {
2127a3df083aSStefano Zampini     *B = An;
2128a3df083aSStefano Zampini   }
2129a3df083aSStefano Zampini   PetscFunctionReturn(0);
2130a3df083aSStefano Zampini }
2131a3df083aSStefano Zampini 
21321cf9b237SStefano Zampini /* TODO: add reuse flag */
21331cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
21341cf9b237SStefano Zampini {
21351cf9b237SStefano Zampini   Mat            Bt;
21361cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
21371cf9b237SStefano Zampini   const PetscInt *ii,*ij;
21381cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
21391cf9b237SStefano Zampini   PetscBool      flg_row;
21401cf9b237SStefano Zampini   PetscErrorCode ierr;
21411cf9b237SStefano Zampini 
21421cf9b237SStefano Zampini   PetscFunctionBegin;
21431cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
21441cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21451cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
21461cf9b237SStefano Zampini   nnz = n;
21471cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21481cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21491cf9b237SStefano Zampini   }
21501cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
21511cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
21521cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
21531cf9b237SStefano Zampini   nnz = 0;
21541cf9b237SStefano Zampini   bii[0] = 0;
21551cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21561cf9b237SStefano Zampini     PetscInt j;
21571cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21581cf9b237SStefano Zampini       PetscScalar entry = a[j];
21593272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21601cf9b237SStefano Zampini         bij[nnz] = ij[j];
21611cf9b237SStefano Zampini         bdata[nnz] = entry;
21621cf9b237SStefano Zampini         nnz++;
21631cf9b237SStefano Zampini       }
21641cf9b237SStefano Zampini     }
21651cf9b237SStefano Zampini     bii[i+1] = nnz;
21661cf9b237SStefano Zampini   }
21671cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21681cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21691cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21701cf9b237SStefano Zampini   {
21711cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21721cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21731cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21741cf9b237SStefano Zampini   }
21753272d46bSStefano Zampini   if (*B == A) {
21763272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21773272d46bSStefano Zampini   }
21781cf9b237SStefano Zampini   *B = Bt;
21791cf9b237SStefano Zampini   PetscFunctionReturn(0);
21801cf9b237SStefano Zampini }
21811cf9b237SStefano Zampini 
21828361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21834f1b2e48SStefano Zampini {
2184c80a6c00SStefano Zampini   Mat                    B = NULL;
2185c80a6c00SStefano Zampini   DM                     dm;
21864f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21874f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21884f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2189c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21904f1b2e48SStefano Zampini   PetscInt               i,n;
21914f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2192c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21934f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21944f1b2e48SStefano Zampini 
21954f1b2e48SStefano Zampini   PetscFunctionBegin;
2196a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2197a2eca866SStefano Zampini   if (cc) *cc = NULL;
2198a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2199c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2200c80a6c00SStefano Zampini   ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
22014f819b78SStefano Zampini   if (!dm) {
22024f819b78SStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2203c80a6c00SStefano Zampini   }
2204c80a6c00SStefano Zampini   if (dm) {
2205c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2206c80a6c00SStefano Zampini   }
22078361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
22088361f951SStefano Zampini 
2209c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2210c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2211c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2212c80a6c00SStefano Zampini     IS             cellNumbering;
2213c80a6c00SStefano Zampini     const PetscInt *cellNum;
2214c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2215c80a6c00SStefano Zampini     PetscSection   section;
2216c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2217c80a6c00SStefano Zampini     PetscSF        sfPoint;
2218c80a6c00SStefano Zampini     PetscErrorCode ierr;
2219c80a6c00SStefano Zampini 
2220c80a6c00SStefano Zampini     PetscFunctionBegin;
2221c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2222c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2223c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2224c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2225c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2226c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2227c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2228c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2229b0441da4SMatthew G. Knepley     ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr);
2230b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
2231956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2232c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2233c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2234c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2235c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2236c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2237c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2238c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2239c80a6c00SStefano Zampini         const PetscInt point = adj[a];
22405cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2241c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2242c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2243c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2244c80a6c00SStefano Zampini           *pBuf = point;
2245c80a6c00SStefano Zampini         }
2246c80a6c00SStefano Zampini       }
2247c80a6c00SStefano Zampini       n++;
2248c80a6c00SStefano Zampini     }
2249b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr);
2250c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2251c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2252c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2253c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2254c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2255c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2256c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2257c80a6c00SStefano Zampini     }
2258c80a6c00SStefano Zampini     xadj[n] = size;
2259c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2260c80a6c00SStefano Zampini     /* Clean up */
2261c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2262c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2263c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2264c80a6c00SStefano Zampini     graph->xadj = xadj;
2265c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2266c80a6c00SStefano Zampini   } else {
2267c80a6c00SStefano Zampini     Mat       A;
22688361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2269c80a6c00SStefano Zampini 
2270c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
227163c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2272a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
227363c961adSStefano Zampini       PetscFunctionReturn(0);
227463c961adSStefano Zampini     }
22757ebab0bbSStefano Zampini     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22764f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22771cf9b237SStefano Zampini       PetscBool isseqdense;
22781cf9b237SStefano Zampini 
22791cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22801cf9b237SStefano Zampini       if (!isseqdense) {
22814f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22821cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22831cf9b237SStefano Zampini         PetscScalar *array;
22841cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22851cf9b237SStefano Zampini 
22861cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22871cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22881cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22891cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22901cf9b237SStefano Zampini           PetscInt j;
22911cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22921cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22931cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22941cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22951cf9b237SStefano Zampini           }
22961cf9b237SStefano Zampini         }
22971cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22989d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22991cf9b237SStefano Zampini       }
23004f1b2e48SStefano Zampini     } else {
2301c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
23024f1b2e48SStefano Zampini       B = A;
23034f1b2e48SStefano Zampini     }
23044f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23054f1b2e48SStefano Zampini 
23064f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
23074f1b2e48SStefano Zampini     if (filter) {
23084f1b2e48SStefano Zampini       PetscScalar *data;
23094f1b2e48SStefano Zampini       PetscInt    j,cum;
23104f1b2e48SStefano Zampini 
23114f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
23124f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
23134f1b2e48SStefano Zampini       cum = 0;
23144f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
23154f1b2e48SStefano Zampini         PetscInt t;
23164f1b2e48SStefano Zampini 
23174f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
23184f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
23194f1b2e48SStefano Zampini             continue;
23204f1b2e48SStefano Zampini           }
23214f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
23224f1b2e48SStefano Zampini         }
23234f1b2e48SStefano Zampini         t = xadj_filtered[i];
23244f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
23254f1b2e48SStefano Zampini         cum += t;
23264f1b2e48SStefano Zampini       }
23274f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
23284f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
23294f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
23304f1b2e48SStefano Zampini     } else {
23314f1b2e48SStefano Zampini       graph->xadj = xadj;
23324f1b2e48SStefano Zampini       graph->adjncy = adjncy;
23334f1b2e48SStefano Zampini     }
2334c80a6c00SStefano Zampini   }
2335c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2336c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2337c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2338c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2339c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2340c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
23414f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
23424f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2343c80a6c00SStefano Zampini 
23444f1b2e48SStefano Zampini   /* partial clean up */
23454f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2346c80a6c00SStefano Zampini   if (B) {
2347c80a6c00SStefano Zampini     PetscBool flg_row;
23484f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23494f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
23504f1b2e48SStefano Zampini   }
2351c80a6c00SStefano Zampini   if (isplex) {
2352c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2353c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2354c80a6c00SStefano Zampini   }
23554f1b2e48SStefano Zampini 
23564f1b2e48SStefano Zampini   /* get back data */
2357c80a6c00SStefano Zampini   if (isplex) {
2358c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2359c80a6c00SStefano Zampini     if (cc || primalv) {
2360c80a6c00SStefano Zampini       Mat          A;
2361c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2362c80a6c00SStefano Zampini       PetscSection subSection;
2363c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2364c80a6c00SStefano Zampini 
2365c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2366c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2367c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2368c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2369c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2370c80a6c00SStefano Zampini 
2371c80a6c00SStefano Zampini       cids[0] = 0;
2372c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2373c80a6c00SStefano Zampini         PetscInt j;
2374c80a6c00SStefano Zampini 
2375c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2376c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2377c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2378c80a6c00SStefano Zampini 
2379c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2380c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
238120c3699dSStefano Zampini             PetscInt s, pp, p = closure[k], off, dof, cdof;
2382c80a6c00SStefano Zampini 
2383c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection,p,&cdof);CHKERRQ(ierr);
2384c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2385c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2386c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2387c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2388c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2389c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2390c80a6c00SStefano Zampini               } else { /* cross-vertex */
2391c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2392c80a6c00SStefano Zampini               }
2393c80a6c00SStefano Zampini             }
239420c3699dSStefano Zampini             ierr = DMPlexGetTreeParent(dm,p,&pp,NULL);CHKERRQ(ierr);
239520c3699dSStefano Zampini             if (pp != p) {
239620c3699dSStefano Zampini               ierr = PetscSectionGetConstraintDof(subSection,pp,&cdof);CHKERRQ(ierr);
239720c3699dSStefano Zampini               ierr = PetscSectionGetOffset(subSection,pp,&off);CHKERRQ(ierr);
239820c3699dSStefano Zampini               ierr = PetscSectionGetDof(subSection,pp,&dof);CHKERRQ(ierr);
239920c3699dSStefano Zampini               for (s = 0; s < dof-cdof; s++) {
240020c3699dSStefano Zampini                 if (PetscBTLookupSet(btvt,off+s)) continue;
240120c3699dSStefano Zampini                 if (!PetscBTLookup(btv,off+s)) {
240220c3699dSStefano Zampini                   ids[cum++] = off+s;
240320c3699dSStefano Zampini                 } else { /* cross-vertex */
240420c3699dSStefano Zampini                   pids[cump++] = off+s;
240520c3699dSStefano Zampini                 }
240620c3699dSStefano Zampini               }
240720c3699dSStefano Zampini             }
2408c80a6c00SStefano Zampini           }
2409c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2410c80a6c00SStefano Zampini         }
2411c80a6c00SStefano Zampini         cids[i+1] = cum;
2412c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2413c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2414c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2415c80a6c00SStefano Zampini         }
2416c80a6c00SStefano Zampini       }
2417c80a6c00SStefano Zampini       if (cc) {
2418c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2419c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2420c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2421c80a6c00SStefano Zampini         }
2422c80a6c00SStefano Zampini         *cc = cc_n;
2423c80a6c00SStefano Zampini       }
2424c80a6c00SStefano Zampini       if (primalv) {
2425c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2426c80a6c00SStefano Zampini       }
2427c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2428c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2429c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2430c80a6c00SStefano Zampini     }
2431c80a6c00SStefano Zampini   } else {
24321cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
24331cf9b237SStefano Zampini     if (cc) {
24344f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
24354f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
24364f1b2e48SStefano 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);
24374f1b2e48SStefano Zampini       }
24384f1b2e48SStefano Zampini       *cc = cc_n;
24391cf9b237SStefano Zampini     }
2440c80a6c00SStefano Zampini   }
24414f1b2e48SStefano Zampini   /* clean up graph */
24424f1b2e48SStefano Zampini   graph->xadj = 0;
24434f1b2e48SStefano Zampini   graph->adjncy = 0;
24444f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
24454f1b2e48SStefano Zampini   PetscFunctionReturn(0);
24464f1b2e48SStefano Zampini }
24474f1b2e48SStefano Zampini 
24485408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
24495408967cSStefano Zampini {
24505408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24515408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2452dee84bffSStefano Zampini   IS             dirIS = NULL;
24534f1b2e48SStefano Zampini   PetscInt       i;
24545408967cSStefano Zampini   PetscErrorCode ierr;
24555408967cSStefano Zampini 
24565408967cSStefano Zampini   PetscFunctionBegin;
2457dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
24585408967cSStefano Zampini   if (zerodiag) {
24595408967cSStefano Zampini     Mat            A;
24605408967cSStefano Zampini     Vec            vec3_N;
24615408967cSStefano Zampini     PetscScalar    *vals;
24625408967cSStefano Zampini     const PetscInt *idxs;
2463d12d3064SStefano Zampini     PetscInt       nz,*count;
24645408967cSStefano Zampini 
24655408967cSStefano Zampini     /* p0 */
24665408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
24675408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24685408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24695408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24704f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24715408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24725408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24735408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24745408967cSStefano Zampini     /* v_I */
24755408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24765408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24775408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24785408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24795408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24805408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24815408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24825408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24835408967cSStefano Zampini     if (dirIS) {
24845408967cSStefano Zampini       PetscInt n;
24855408967cSStefano Zampini 
24865408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24875408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24885408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24895408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24905408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24915408967cSStefano Zampini     }
24925408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24935408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24945408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24955408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2496669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24975408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24985408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24999a962809SStefano 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]));
25005408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
25015408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2502d12d3064SStefano Zampini 
2503d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2504d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2505d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2506d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2507d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2508d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25096080607fSStefano 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]);
2510d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2511d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
25125408967cSStefano Zampini   }
2513dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
25145408967cSStefano Zampini 
25155408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
25165408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
25174f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
25185408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
25194f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
25205408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2521f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2522f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
25236080607fSStefano Zampini     if (val != -PetscGlobalRank-i) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %D instead of %g",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i);
2524f2a566d8SStefano Zampini   }
25255408967cSStefano Zampini   PetscFunctionReturn(0);
25265408967cSStefano Zampini }
25275408967cSStefano Zampini 
25283b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2529339f8db1SStefano Zampini {
2530339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
25313b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
25323b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
25334edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
25344edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2535339f8db1SStefano Zampini   PetscErrorCode ierr;
2536339f8db1SStefano Zampini 
2537339f8db1SStefano Zampini   PetscFunctionBegin;
25383b03f7bbSStefano Zampini   if (reuse) goto project_b0;
25399f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
25409f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2541a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2542a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2543a3df083aSStefano Zampini   }
2544a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
25453b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
25463b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
25473b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
25483b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
25494f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
25504f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
25511ae86dd6SStefano Zampini      since the local Schur complements are already SPD
25524f1b2e48SStefano Zampini   */
255340fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
25547fbe2174Sstefano_zampini     IS        iP = NULL;
25553b03f7bbSStefano Zampini     PetscInt  p,*pp;
25563b03f7bbSStefano Zampini     PetscBool flg;
25574f1b2e48SStefano Zampini 
25583b03f7bbSStefano Zampini     ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp);CHKERRQ(ierr);
25593b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
256028b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
25613b03f7bbSStefano Zampini     ierr = PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg);CHKERRQ(ierr);
256228b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
25633b03f7bbSStefano Zampini     if (!flg) {
25643b03f7bbSStefano Zampini       n = 1;
25653b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25663b03f7bbSStefano Zampini     }
25673b03f7bbSStefano Zampini 
25683b03f7bbSStefano Zampini     bsp = 0;
25693b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25703b03f7bbSStefano Zampini       PetscInt bs;
25713b03f7bbSStefano Zampini 
25723b03f7bbSStefano Zampini       if (pp[p] < 0 || pp[p] > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",pp[p]);
25733b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25743b03f7bbSStefano Zampini       bsp += bs;
25753b03f7bbSStefano Zampini     }
25763b03f7bbSStefano Zampini     ierr = PetscMalloc1(bsp,&bzerodiag);CHKERRQ(ierr);
25773b03f7bbSStefano Zampini     bsp  = 0;
25783b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25793b03f7bbSStefano Zampini       const PetscInt *idxs;
25803b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25813b03f7bbSStefano Zampini 
25823b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25833b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl);CHKERRQ(ierr);
25843b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25853b03f7bbSStefano Zampini       ierr = PetscMalloc1(npl/bs,&bidxs);CHKERRQ(ierr);
25863b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25873b03f7bbSStefano Zampini         PetscInt i;
25883b03f7bbSStefano Zampini 
25893b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25903b03f7bbSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]);CHKERRQ(ierr);
25913b03f7bbSStefano Zampini         bsp++;
25923b03f7bbSStefano Zampini       }
25933b03f7bbSStefano Zampini       ierr = PetscFree(bidxs);CHKERRQ(ierr);
25943b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25953b03f7bbSStefano Zampini     }
25963b03f7bbSStefano Zampini     ierr = ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures);CHKERRQ(ierr);
25973b03f7bbSStefano Zampini 
25987fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25997fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
26007fbe2174Sstefano_zampini     if (iP) {
26017fbe2174Sstefano_zampini       IS newpressures;
26027fbe2174Sstefano_zampini 
26037fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
26047fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
26057fbe2174Sstefano_zampini       pressures = newpressures;
26067fbe2174Sstefano_zampini     }
260740fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
260840fa8d13SStefano Zampini     if (!sorted) {
260940fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
261040fa8d13SStefano Zampini     }
26113b03f7bbSStefano Zampini     ierr = PetscFree(pp);CHKERRQ(ierr);
261240fa8d13SStefano Zampini   }
26133b03f7bbSStefano Zampini 
261497d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
261597d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
261627b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
261797d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2618339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2619339f8db1SStefano Zampini   if (!sorted) {
2620339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2621339f8db1SStefano Zampini   }
26224edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26234edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2624339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26254f1b2e48SStefano Zampini   if (!nz) {
26264f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
26274f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
262840fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
262940fa8d13SStefano Zampini   }
26304f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
26313b03f7bbSStefano Zampini 
26324f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
26334f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
26343b03f7bbSStefano Zampini   benign_n         = 0;
26351f4df5f7SStefano Zampini   n_interior_dofs  = 0;
26361f4df5f7SStefano Zampini   interior_dofs    = NULL;
26374edc6404Sstefano_zampini   nneu             = 0;
26384edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
26394edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
26404edc6404Sstefano_zampini   }
26413369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
26424edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
26431f4df5f7SStefano Zampini     PetscInt n,i,j;
26441f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
26451f4df5f7SStefano Zampini     PetscInt *iwork;
26461f4df5f7SStefano Zampini 
26471f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
26481f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26491f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
26501f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
265190648384SStefano Zampini     for (i=1;i<n_neigh;i++)
26521f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
26531f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
26541f4df5f7SStefano Zampini     for (i=0;i<n;i++)
26551f4df5f7SStefano Zampini       if (!iwork[i])
26561f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
26571f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
26581f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26591f4df5f7SStefano Zampini   }
26604f1b2e48SStefano Zampini   if (has_null_pressures) {
26614f1b2e48SStefano Zampini     IS             *subs;
26624edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26631f4df5f7SStefano Zampini     const PetscInt *idxs;
26641f4df5f7SStefano Zampini     PetscScalar    *array;
26651f4df5f7SStefano Zampini     Vec            *work;
26661f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
26674f1b2e48SStefano Zampini 
26684f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26694f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26701f4df5f7SStefano 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) */
26714edc6404Sstefano_zampini     if (checkb) {
26721f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
26731f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
26741f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
26751f4df5f7SStefano Zampini       /* work[0] = 1_p */
26761f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
26771f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
26781f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26791f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
26801f4df5f7SStefano Zampini       /* work[0] = 1_v */
26811f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
26821f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
26831f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26841f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
26851f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
26861f4df5f7SStefano Zampini     }
26873b03f7bbSStefano Zampini 
26883b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26893b03f7bbSStefano Zampini       IS       *is;
26903b03f7bbSStefano Zampini       PetscInt b,totb;
26913b03f7bbSStefano Zampini 
26923b03f7bbSStefano Zampini       totb  = bsp;
26933b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26943b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
26953b03f7bbSStefano Zampini       ierr  = PetscCalloc1(nsubs*totb,&zerodiag_subs);CHKERRQ(ierr);
26963b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
26974f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
26984f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
26994f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
27004f1b2e48SStefano Zampini           PetscInt               nl;
27014f1b2e48SStefano Zampini 
27023b03f7bbSStefano Zampini           if (subs) {
27034f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
27043b03f7bbSStefano Zampini           } else {
27053b03f7bbSStefano Zampini             IS tis;
27063b03f7bbSStefano Zampini 
27073b03f7bbSStefano Zampini             ierr = MatGetLocalSize(pcbddc->local_mat,&nl,NULL);CHKERRQ(ierr);
27083b03f7bbSStefano Zampini             ierr = ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis);CHKERRQ(ierr);
27093b03f7bbSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(tis,&l2g);CHKERRQ(ierr);
27103b03f7bbSStefano Zampini             ierr = ISDestroy(&tis);CHKERRQ(ierr);
27113b03f7bbSStefano Zampini           }
27123b03f7bbSStefano Zampini           ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs);CHKERRQ(ierr);
27134f1b2e48SStefano Zampini           ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
27144f1b2e48SStefano Zampini           if (nl) {
27154f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
27164f1b2e48SStefano Zampini 
27174edc6404Sstefano_zampini             if (checkb) {
27181f4df5f7SStefano Zampini               ierr = VecSet(matis->x,0);CHKERRQ(ierr);
27191f4df5f7SStefano Zampini               ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
27201f4df5f7SStefano Zampini               ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
27211f4df5f7SStefano Zampini               ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27221f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
27231f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27241f4df5f7SStefano Zampini               ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
27251f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
27261f4df5f7SStefano Zampini               ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
27271f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
27281f4df5f7SStefano Zampini               ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
27291f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
27301f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27311f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
27321f4df5f7SStefano Zampini                   break;
27331f4df5f7SStefano Zampini                 }
27341f4df5f7SStefano Zampini               }
27351f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
27361f4df5f7SStefano Zampini             }
27376632bad2Sstefano_zampini             if (valid && nneu) {
27386632bad2Sstefano_zampini               const PetscInt *idxs;
27391f4df5f7SStefano Zampini               PetscInt       nzb;
27401f4df5f7SStefano Zampini 
27416632bad2Sstefano_zampini               ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27426632bad2Sstefano_zampini               ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
27436632bad2Sstefano_zampini               ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27441f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
27451f4df5f7SStefano Zampini             }
27461f4df5f7SStefano Zampini             if (valid && pressures) {
27473b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
27483b03f7bbSStefano Zampini               PetscInt i1,i2;
27493b03f7bbSStefano Zampini 
27504f1b2e48SStefano Zampini               ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
27513b03f7bbSStefano Zampini               ierr = ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp);CHKERRQ(ierr);
27523b03f7bbSStefano Zampini               ierr = ISGetLocalSize(tmp,&i1);CHKERRQ(ierr);
27533b03f7bbSStefano Zampini               ierr = ISGetLocalSize(t_zerodiag_subs,&i2);CHKERRQ(ierr);
27543b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
27554f1b2e48SStefano Zampini               ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
27563b03f7bbSStefano Zampini               ierr = ISDestroy(&tmp);CHKERRQ(ierr);
27574f1b2e48SStefano Zampini             }
27584f1b2e48SStefano Zampini             if (valid) {
27593b03f7bbSStefano Zampini               ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]);CHKERRQ(ierr);
27603b03f7bbSStefano Zampini               benign_n++;
27613b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27624f1b2e48SStefano Zampini           }
27634f1b2e48SStefano Zampini           ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
27644f1b2e48SStefano Zampini           ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
27654f1b2e48SStefano Zampini         }
27663b03f7bbSStefano Zampini       }
27674f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27684f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27691f4df5f7SStefano Zampini 
27706632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27711f4df5f7SStefano Zampini       if (valid && pressures) {
27724f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
27734f1b2e48SStefano Zampini       }
27744edc6404Sstefano_zampini       if (valid && checkb) {
27751f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
27761f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
27771f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27781f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27791f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27801f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27811f4df5f7SStefano Zampini             break;
27821f4df5f7SStefano Zampini           }
27831f4df5f7SStefano Zampini         }
27841f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27851f4df5f7SStefano Zampini       }
27864f1b2e48SStefano Zampini       if (valid) {
27873b03f7bbSStefano Zampini         benign_n = 1;
27883b03f7bbSStefano Zampini         ierr = PetscMalloc1(benign_n,&zerodiag_subs);CHKERRQ(ierr);
27894f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
27904f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27914f1b2e48SStefano Zampini       }
27924f1b2e48SStefano Zampini     }
27934edc6404Sstefano_zampini     if (checkb) {
27941f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
27954f1b2e48SStefano Zampini     }
27961f4df5f7SStefano Zampini   }
27971f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
27984f1b2e48SStefano Zampini 
27993b03f7bbSStefano Zampini   if (!benign_n) {
2800b9b0e38cSStefano Zampini     PetscInt n;
2801b9b0e38cSStefano Zampini 
28024f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28034f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2804b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
280576a58201SStefano Zampini     if (n) have_null = PETSC_FALSE;
2806b9b0e38cSStefano Zampini   }
28074f1b2e48SStefano Zampini 
28084f1b2e48SStefano Zampini   /* final check for null pressures */
28094f1b2e48SStefano Zampini   if (zerodiag && pressures) {
28103b03f7bbSStefano Zampini     ierr = ISEqual(pressures,zerodiag,&have_null);CHKERRQ(ierr);
28114f1b2e48SStefano Zampini   }
28124f1b2e48SStefano Zampini 
28134f1b2e48SStefano Zampini   if (recompute_zerodiag) {
28144f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28153b03f7bbSStefano Zampini     if (benign_n == 1) {
28164f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
28174f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
28184f1b2e48SStefano Zampini     } else {
28194f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
28204f1b2e48SStefano Zampini 
28214f1b2e48SStefano Zampini       nzn = 0;
28223b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28234f1b2e48SStefano Zampini         PetscInt ns;
28244f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28254f1b2e48SStefano Zampini         nzn += ns;
28264f1b2e48SStefano Zampini       }
28274f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
28284f1b2e48SStefano Zampini       nzn = 0;
28293b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28304f1b2e48SStefano Zampini         PetscInt ns,*idxs;
28314f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28324f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2833580bdb30SBarry Smith         ierr = PetscArraycpy(new_idxs+nzn,idxs,ns);CHKERRQ(ierr);
28344f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
28354f1b2e48SStefano Zampini         nzn += ns;
28364f1b2e48SStefano Zampini       }
28374f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
28384f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
28394f1b2e48SStefano Zampini     }
28404f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
28414f1b2e48SStefano Zampini   }
28424f1b2e48SStefano Zampini 
28433b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
28443b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
28453b03f7bbSStefano Zampini 
2846669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2847a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2848a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2849a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2850a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2851a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2852a198735bSStefano Zampini 
28531f4df5f7SStefano Zampini     if (pressures) {
28541f4df5f7SStefano Zampini       isused = pressures;
28551f4df5f7SStefano Zampini     } else {
28564edc6404Sstefano_zampini       isused = zerodiag_save;
28571f4df5f7SStefano Zampini     }
2858a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2859669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
28601ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
28611ae86dd6SStefano 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");
2862a198735bSStefano Zampini     n_isused = 0;
2863a198735bSStefano Zampini     if (isused) {
2864a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2865a198735bSStefano Zampini     }
2866a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2867a198735bSStefano Zampini     st = st-n_isused;
28681ae86dd6SStefano Zampini     if (n) {
2869a198735bSStefano Zampini       const PetscInt *gidxs;
2870a198735bSStefano Zampini 
28717dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2872a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2873a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2874a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2875a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2876a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
28771ae86dd6SStefano Zampini     } else {
2878a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2879a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2880a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2881a198735bSStefano Zampini     }
2882a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2883a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2884a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2885a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2886a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2887a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2888a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2889a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2890a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2891a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2892a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2893a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2894a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2895a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
28961ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28971ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28981ae86dd6SStefano Zampini   }
28994edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
29003b03f7bbSStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
29013b03f7bbSStefano Zampini   if (bzerodiag) {
29023b03f7bbSStefano Zampini     PetscInt i;
2903b3afcdbeSStefano Zampini 
29043b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
29053b03f7bbSStefano Zampini       ierr = ISDestroy(&bzerodiag[i]);CHKERRQ(ierr);
29063b03f7bbSStefano Zampini     }
29073b03f7bbSStefano Zampini     ierr = PetscFree(bzerodiag);CHKERRQ(ierr);
29083b03f7bbSStefano Zampini   }
29093b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
29103b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
29113b03f7bbSStefano Zampini 
29123b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
29133b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
29143b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
29153b03f7bbSStefano Zampini 
29163b03f7bbSStefano Zampini project_b0:
2917aa0d93e9SStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2918b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
29193b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
29204f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
29214f1b2e48SStefano Zampini 
2922339f8db1SStefano Zampini     /* local change of basis for pressures */
2923339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
292497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2925339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2926339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2927339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
2928aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
29294f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2930aa0d93e9SStefano Zampini       const PetscInt *idxs;
29314f1b2e48SStefano Zampini       PetscInt       nzs,j;
29324f1b2e48SStefano Zampini 
29333b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs);CHKERRQ(ierr);
29343b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29354f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
29364f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
29373b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29384f1b2e48SStefano Zampini     }
2939339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2940e1b21442SStefano Zampini     ierr = MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2941339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2942aa0d93e9SStefano Zampini     /* set identity by default */
2943aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
2944aa0d93e9SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES);CHKERRQ(ierr);
2945339f8db1SStefano Zampini     }
29469f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
29474f1b2e48SStefano 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);
2948339f8db1SStefano Zampini     /* set change on pressures */
29494f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
29504f1b2e48SStefano Zampini       PetscScalar    *array;
2951aa0d93e9SStefano Zampini       const PetscInt *idxs;
29524f1b2e48SStefano Zampini       PetscInt       nzs;
29534f1b2e48SStefano Zampini 
29543b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs);CHKERRQ(ierr);
29553b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
29564f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2957339f8db1SStefano Zampini         PetscScalar vals[2];
2958339f8db1SStefano Zampini         PetscInt    cols[2];
2959339f8db1SStefano Zampini 
2960339f8db1SStefano Zampini         cols[0] = idxs[i];
29614f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2962339f8db1SStefano Zampini         vals[0] = 1.;
2963b0f5fe93SStefano Zampini         vals[1] = 1.;
29644f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2965339f8db1SStefano Zampini       }
29664f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
29674f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29684f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29694f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
29704f1b2e48SStefano Zampini       /* store local idxs for p0 */
29714f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29723b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2973339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
29744f1b2e48SStefano Zampini     }
2975339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2976339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29773b03f7bbSStefano Zampini 
2978a3df083aSStefano Zampini     /* project if needed */
2979a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29801dd7afcfSStefano Zampini       Mat M;
29811dd7afcfSStefano Zampini 
29821dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2983339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
29841dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
29851dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2986a3df083aSStefano Zampini     }
29874f1b2e48SStefano Zampini     /* store global idxs for p0 */
29884f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2989339f8db1SStefano Zampini   }
2990339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2991339f8db1SStefano Zampini   PetscFunctionReturn(0);
2992339f8db1SStefano Zampini }
2993339f8db1SStefano Zampini 
2994015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2995efc2fbd9SStefano Zampini {
2996efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2997de9d7bd0SStefano Zampini   PetscScalar    *array;
2998efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2999efc2fbd9SStefano Zampini 
3000efc2fbd9SStefano Zampini   PetscFunctionBegin;
3001efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
3002efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
30034f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
3004efc2fbd9SStefano Zampini   }
3005de9d7bd0SStefano Zampini   if (get) {
3006efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
30074f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
30084f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
3009efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
3010de9d7bd0SStefano Zampini   } else {
3011de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
3012de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
3013de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
3014de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
3015efc2fbd9SStefano Zampini   }
3016efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
3017efc2fbd9SStefano Zampini }
3018efc2fbd9SStefano Zampini 
3019c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
3020c263805aSStefano Zampini {
3021c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3022c263805aSStefano Zampini   PetscErrorCode ierr;
3023c263805aSStefano Zampini 
3024c263805aSStefano Zampini   PetscFunctionBegin;
3025c263805aSStefano Zampini   /* TODO: add error checking
3026c263805aSStefano Zampini     - avoid nested pop (or push) calls.
3027c263805aSStefano Zampini     - cannot push before pop.
30281c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
3029c263805aSStefano Zampini   */
30304f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3031efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
3032efc2fbd9SStefano Zampini   }
3033c263805aSStefano Zampini   if (pop) {
3034a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30354f1b2e48SStefano Zampini       IS       is_p0;
30364f1b2e48SStefano Zampini       MatReuse reuse;
3037c263805aSStefano Zampini 
3038c263805aSStefano Zampini       /* extract B_0 */
30394f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
30404f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
30414f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
30424f1b2e48SStefano Zampini       }
30434f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
30447dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
3045c263805aSStefano Zampini       /* remove rows and cols from local problem */
3046c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
304797d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
30484f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
30494f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
3050a3df083aSStefano Zampini     } else {
3051a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
3052a3df083aSStefano Zampini       PetscScalar *vals;
3053a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
3054a3df083aSStefano Zampini 
3055a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
3056a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
3057a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30580b5adadeSStefano Zampini         PetscInt *nnz;
3059a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
3060a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
3061a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3062331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
3063331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
3064331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
3065331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3066331e053bSStefano Zampini         }
3067331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
3068e1b21442SStefano Zampini         ierr = MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3069331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
3070331e053bSStefano Zampini       }
3071a3df083aSStefano Zampini 
3072a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3073a3df083aSStefano Zampini         PetscScalar *array;
3074a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3075a3df083aSStefano Zampini 
3076a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
3077a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3078a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3079a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
3080a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
3081a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
3082a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
3083a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
3084a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
3085a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
3086a3df083aSStefano Zampini         cum = 0;
3087a3df083aSStefano Zampini         for (j=0;j<n;j++) {
308822db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3089a3df083aSStefano Zampini             vals[cum] = array[j];
3090a3df083aSStefano Zampini             idxs_ins[cum] = j;
3091a3df083aSStefano Zampini             cum++;
3092a3df083aSStefano Zampini           }
3093a3df083aSStefano Zampini         }
3094a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
3095a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
3096a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3097a3df083aSStefano Zampini       }
3098a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3099a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3100a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
3101a3df083aSStefano Zampini     }
3102c263805aSStefano Zampini   } else { /* push */
3103a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
31044f1b2e48SStefano Zampini       PetscInt i;
31054f1b2e48SStefano Zampini 
31064f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
31074f1b2e48SStefano Zampini         PetscScalar *B0_vals;
31084f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
31094f1b2e48SStefano Zampini 
31104f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31114f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31127b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31134f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
31144f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31154f1b2e48SStefano Zampini       }
3116c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3117c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31186080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3119c263805aSStefano Zampini   }
3120c263805aSStefano Zampini   PetscFunctionReturn(0);
3121c263805aSStefano Zampini }
3122c263805aSStefano Zampini 
312308122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3124b1b3d7a2SStefano Zampini {
3125b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
312608122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
312708122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
312808122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
312908122e43SStefano Zampini   PetscScalar     *work,lwork;
313008122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
313108122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3132bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
31331b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3134f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
313508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
313608122e43SStefano Zampini   PetscReal       *rwork;
313708122e43SStefano Zampini #endif
3138b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3139b1b3d7a2SStefano Zampini 
3140b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3141b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3142af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3143bd2a564bSStefano 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);
314443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
314506a4e24aSStefano Zampini 
3146fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3147fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3148fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3149fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
31501575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3151fd14bc51SStefano Zampini   }
3152fd14bc51SStefano Zampini 
3153e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
31546080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %D (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);CHKERRQ(ierr);
3155e496cd5dSStefano Zampini   }
3156e496cd5dSStefano Zampini 
315708122e43SStefano Zampini   /* max size of subsets */
315808122e43SStefano Zampini   mss = 0;
315908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
316008122e43SStefano Zampini     PetscInt subset_size;
3161862806e4SStefano Zampini 
316208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
316308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
316408122e43SStefano Zampini   }
316508122e43SStefano Zampini 
316608122e43SStefano Zampini   /* min/max and threshold */
316708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3168f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
316908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3170f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3171bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3172f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3173f6f667cfSStefano Zampini   }
317408122e43SStefano Zampini 
317508122e43SStefano Zampini   /* allocate lapack workspace */
317608122e43SStefano Zampini   cum = cum2 = 0;
317708122e43SStefano Zampini   maxneigs = 0;
317808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
317908122e43SStefano Zampini     PetscInt n,subset_size;
3180f6f667cfSStefano Zampini 
318108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
318208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31839162d606SStefano Zampini     cum += subset_size;
31849162d606SStefano Zampini     cum2 += subset_size*n;
318508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
318608122e43SStefano Zampini   }
31877ebab0bbSStefano Zampini   lwork = 0;
318808122e43SStefano Zampini   if (mss) {
3189bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
31907ebab0bbSStefano Zampini       PetscScalar  sdummy = 0.;
319108122e43SStefano Zampini       PetscBLASInt B_itype = 1;
31927ebab0bbSStefano Zampini       PetscBLASInt B_N = mss, idummy = 0;
31937ebab0bbSStefano Zampini       PetscReal    rdummy = 0.,zero = 0.0;
31944c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
319508122e43SStefano Zampini 
319608122e43SStefano Zampini       B_lwork = -1;
31977ebab0bbSStefano Zampini       /* some implementations may complain about NULL pointers, even if we are querying */
31987ebab0bbSStefano Zampini       S = &sdummy;
31997ebab0bbSStefano Zampini       St = &sdummy;
32007ebab0bbSStefano Zampini       eigs = &rdummy;
32017ebab0bbSStefano Zampini       eigv = &sdummy;
32027ebab0bbSStefano Zampini       B_iwork = &idummy;
32037ebab0bbSStefano Zampini       B_ifail = &idummy;
3204d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32057ebab0bbSStefano Zampini       rwork = &rdummy;
3206d1710679SStefano Zampini #endif
32078bec7fa6SStefano Zampini       thresh = 1.0;
320808122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
320908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
321008122e43SStefano 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));
321108122e43SStefano Zampini #else
321208122e43SStefano 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));
321308122e43SStefano Zampini #endif
321408122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
321508122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3216bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
321708122e43SStefano Zampini   }
321808122e43SStefano Zampini 
321908122e43SStefano Zampini   nv = 0;
3220d62866d3SStefano 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) */
3221d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
322208122e43SStefano Zampini   }
32234c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3224f6f667cfSStefano Zampini   if (allocated_S_St) {
3225f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3226f6f667cfSStefano Zampini   }
3227f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
322808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
322908122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
323008122e43SStefano Zampini #endif
32319162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
32329162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
32339162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
323408122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
32359162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
3236580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs);CHKERRQ(ierr);
323708122e43SStefano Zampini 
323808122e43SStefano Zampini   maxneigs = 0;
323972b8c272SStefano Zampini   cum = cumarray = 0;
32409162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
32419162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3242d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
324308122e43SStefano Zampini     const PetscInt *idxs;
324408122e43SStefano Zampini 
3245d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
324608122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
324708122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
324808122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
324908122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
32509162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
32519162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
325208122e43SStefano Zampini     }
3253d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
325408122e43SStefano Zampini   }
325508122e43SStefano Zampini 
325608122e43SStefano Zampini   if (mss) { /* multilevel */
325708122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
325808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
325908122e43SStefano Zampini   }
326008122e43SStefano Zampini 
3261bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3262bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
326308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
326408122e43SStefano Zampini     const PetscInt *idxs;
32659d54b7f4SStefano Zampini     PetscReal      upper,lower;
3266862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
326708122e43SStefano Zampini     PetscBLASInt   B_N;
3268aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3269bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
327008122e43SStefano Zampini 
32719d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
32729d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3273bd2a564bSStefano Zampini       lower = uthresh;
32749d54b7f4SStefano Zampini     } else {
3275bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3276bd2a564bSStefano Zampini       upper = 1./uthresh;
32779d54b7f4SStefano Zampini       lower = 0.;
32789d54b7f4SStefano Zampini     }
3279862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3280ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3281f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3282bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3283bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3284bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3285bd2a564bSStefano Zampini       Mat T;
3286bd2a564bSStefano Zampini 
3287bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3288bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3289bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3290bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3291bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3292bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3293bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3294bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3295bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3296bd2a564bSStefano Zampini             PetscInt       nz,k;
3297bd2a564bSStefano Zampini             const PetscInt *idxs;
3298bd2a564bSStefano Zampini 
3299bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3300bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3301bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3302bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3303bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3304bd2a564bSStefano Zampini             }
3305bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3306bd2a564bSStefano Zampini           }
3307bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3308bd2a564bSStefano Zampini           break;
3309bd2a564bSStefano Zampini         }
3310bd2a564bSStefano Zampini       }
3311bd2a564bSStefano Zampini     }
3312bd2a564bSStefano Zampini 
3313f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3314bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3315aff50787SStefano Zampini         PetscInt j,k;
3316580bdb30SBarry Smith         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */
3317580bdb30SBarry Smith           ierr = PetscArrayzero(S,subset_size*subset_size);CHKERRQ(ierr);
3318580bdb30SBarry Smith           ierr = PetscArrayzero(St,subset_size*subset_size);CHKERRQ(ierr);
331908122e43SStefano Zampini         }
332008122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3321aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3322aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3323aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3324aff50787SStefano Zampini           }
332508122e43SStefano Zampini         }
332608122e43SStefano Zampini       } else {
3327580bdb30SBarry Smith         ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3328580bdb30SBarry Smith         ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
332908122e43SStefano Zampini       }
33308bec7fa6SStefano Zampini     } else {
3331f6f667cfSStefano Zampini       S = Sarray + cumarray;
3332f6f667cfSStefano Zampini       St = Starray + cumarray;
33338bec7fa6SStefano Zampini     }
3334aff50787SStefano Zampini     /* see if we can save some work */
3335b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3336580bdb30SBarry Smith       ierr = PetscArraycmp(S,St,subset_size*subset_size,&same_data);CHKERRQ(ierr);
3337aff50787SStefano Zampini     }
3338aff50787SStefano Zampini 
3339b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3340aff50787SStefano Zampini       B_neigs = 0;
3341aff50787SStefano Zampini     } else {
3342bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
334308122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3344f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
33454c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
33469552c7c7SStefano Zampini         PetscInt     nmin_s;
3347bd2a564bSStefano Zampini         PetscBool    compute_range;
3348bd2a564bSStefano Zampini 
33499036ceccSStefano Zampini         B_neigs = 0;
3350bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3351bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
335208122e43SStefano Zampini 
3353fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
33549036ceccSStefano Zampini           PetscInt nc = 0;
3355d16cbb6bSStefano Zampini 
33569036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
33579036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
33589036ceccSStefano Zampini           }
33596080607fSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %D/%D size %D count %D fid %D (range %d) (change %D).\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]+1,pcbddc->mat_graph->which_dof[idxs[0]],compute_range,nc);CHKERRQ(ierr);
3360b7ab4a40SStefano Zampini         }
3361b7ab4a40SStefano Zampini 
336208122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3363b7ab4a40SStefano Zampini         if (compute_range) {
3364d16cbb6bSStefano Zampini 
3365d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3366bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
336708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33689d54b7f4SStefano 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));
336908122e43SStefano Zampini #else
33709d54b7f4SStefano 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));
337108122e43SStefano Zampini #endif
337243371fb9SStefano Zampini             ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3373bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33749036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3375bd2a564bSStefano Zampini             PetscReal bb[2];
3376bd2a564bSStefano Zampini 
3377bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3378bd2a564bSStefano Zampini             switch (recipe) {
3379bd2a564bSStefano Zampini             case 0:
3380bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3381bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3382bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3383bd2a564bSStefano 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));
3384bd2a564bSStefano Zampini #else
3385bd2a564bSStefano 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));
3386bd2a564bSStefano Zampini #endif
338743371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3388bd2a564bSStefano Zampini               break;
3389bd2a564bSStefano Zampini             case 1:
3390bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3391bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3392bd2a564bSStefano 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));
3393bd2a564bSStefano Zampini #else
3394bd2a564bSStefano 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));
3395bd2a564bSStefano Zampini #endif
339643371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3397bd2a564bSStefano Zampini               if (!scal) {
33989036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3399bd2a564bSStefano Zampini 
3400aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3401580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3402580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3403bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3404bd2a564bSStefano 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));
3405bd2a564bSStefano Zampini #else
3406bd2a564bSStefano 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));
3407bd2a564bSStefano Zampini #endif
340843371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3409bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3410bd2a564bSStefano Zampini               }
3411bd2a564bSStefano Zampini               break;
34129036ceccSStefano Zampini             case 2:
34139036ceccSStefano Zampini               if (scal) {
34149036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
34159036ceccSStefano Zampini                 bb[1] = 0;
34169036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34179036ceccSStefano 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));
34189036ceccSStefano Zampini #else
34199036ceccSStefano 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));
34209036ceccSStefano Zampini #endif
342143371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34229036ceccSStefano Zampini               } else {
34239036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34249036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
34259036ceccSStefano Zampini 
34269036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
34279036ceccSStefano Zampini                 if (lthresh > 0.0) {
34289036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
34299036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
34309036ceccSStefano Zampini 
34319036ceccSStefano Zampini                   import = PETSC_TRUE;
34329036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34339036ceccSStefano 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));
34349036ceccSStefano Zampini #else
34359036ceccSStefano 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));
34369036ceccSStefano Zampini #endif
343743371fb9SStefano Zampini                   ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34389036ceccSStefano Zampini                 }
34399036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
34409036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34419036ceccSStefano Zampini                 if (import) {
3442580bdb30SBarry Smith                   ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3443580bdb30SBarry Smith                   ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34449036ceccSStefano Zampini                 }
34459036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34469036ceccSStefano 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));
34479036ceccSStefano Zampini #else
34489036ceccSStefano 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));
34499036ceccSStefano Zampini #endif
345043371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34519036ceccSStefano Zampini                 B_neigs += B_neigs2;
34529036ceccSStefano Zampini               }
34539036ceccSStefano Zampini               break;
34549036ceccSStefano Zampini             case 3:
34559036ceccSStefano Zampini               if (scal) {
34569036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
34579036ceccSStefano Zampini               } else {
34589036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
34599036ceccSStefano Zampini               }
34609036ceccSStefano Zampini               if (!scal) {
34619036ceccSStefano Zampini                 bb[0] = uthresh;
34629036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34639036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34649036ceccSStefano 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));
34659036ceccSStefano Zampini #else
34669036ceccSStefano 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));
34679036ceccSStefano Zampini #endif
346843371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34699036ceccSStefano Zampini               }
34709036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34719036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34729036ceccSStefano Zampini 
34739036ceccSStefano Zampini                 B_IL = 1;
34749036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
3475580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3476580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34779036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34789036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
34799036ceccSStefano Zampini #else
34809036ceccSStefano Zampini                 PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
34819036ceccSStefano Zampini #endif
348243371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34839036ceccSStefano Zampini                 B_neigs += B_neigs2;
34849036ceccSStefano Zampini               }
34859036ceccSStefano Zampini               break;
348648cebe81SStefano Zampini             case 4:
348748cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
348848cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
348948cebe81SStefano 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));
349048cebe81SStefano Zampini #else
349148cebe81SStefano 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));
349248cebe81SStefano Zampini #endif
349343371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
349448cebe81SStefano Zampini               {
349548cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
349648cebe81SStefano Zampini 
349748cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
3498580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3499580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
350048cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
350148cebe81SStefano 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));
350248cebe81SStefano Zampini #else
350348cebe81SStefano 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));
350448cebe81SStefano Zampini #endif
350543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
350648cebe81SStefano Zampini                 B_neigs += B_neigs2;
350748cebe81SStefano Zampini               }
350848cebe81SStefano Zampini               break;
350980db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
351080db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
351180db8efeSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
351280db8efeSStefano Zampini #else
351380db8efeSStefano Zampini               PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
351480db8efeSStefano Zampini #endif
351543371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
351680db8efeSStefano Zampini               {
351780db8efeSStefano Zampini                 PetscInt e,k,ne;
351880db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
351980db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
352080db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
352180db8efeSStefano Zampini                     eigs[ne] = eigs[e];
352280db8efeSStefano Zampini                     ne++;
352380db8efeSStefano Zampini                   }
352480db8efeSStefano Zampini                 }
3525580bdb30SBarry Smith                 ierr = PetscArraycpy(eigv,S,B_N*ne);CHKERRQ(ierr);
352680db8efeSStefano Zampini                 B_neigs = ne;
352780db8efeSStefano Zampini               }
352880db8efeSStefano Zampini               break;
3529bd2a564bSStefano Zampini             default:
3530bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3531bd2a564bSStefano Zampini               break;
3532bd2a564bSStefano Zampini             }
3533bd2a564bSStefano Zampini           }
3534bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3535d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3536d16cbb6bSStefano Zampini           B_IL = 1;
3537d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
35389d54b7f4SStefano 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));
3539d16cbb6bSStefano Zampini #else
35409d54b7f4SStefano 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));
3541d16cbb6bSStefano Zampini #endif
354243371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3543b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3544b7ab4a40SStefano Zampini           PetscInt k;
3545b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3546b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3547b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3548b7ab4a40SStefano Zampini           nmin = nmax;
3549580bdb30SBarry Smith           ierr = PetscArrayzero(eigv,subset_size*nmax);CHKERRQ(ierr);
3550b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3551b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3552b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3553b7ab4a40SStefano Zampini           }
3554d16cbb6bSStefano Zampini         }
355508122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
355608122e43SStefano Zampini         if (B_ierr) {
35576c4ed002SBarry 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);
35586c4ed002SBarry 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);
35596c4ed002SBarry 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);
356008122e43SStefano Zampini         }
356108122e43SStefano Zampini 
356208122e43SStefano Zampini         if (B_neigs > nmax) {
3563fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35646080607fSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %D.\n",B_neigs,nmax);CHKERRQ(ierr);
3565fd14bc51SStefano Zampini           }
3566bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
356708122e43SStefano Zampini           B_neigs = nmax;
356808122e43SStefano Zampini         }
356908122e43SStefano Zampini 
35709552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35719552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35729036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
357308122e43SStefano Zampini 
35749d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3575bd2a564bSStefano Zampini             if (scal) {
3576bd2a564bSStefano Zampini               B_IU = nmin_s;
3577bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3578bd2a564bSStefano Zampini             } else {
3579f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35809d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3581bd2a564bSStefano Zampini             }
35829d54b7f4SStefano Zampini           } else {
35839d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35849d54b7f4SStefano Zampini             B_IU = nmin_s;
35859d54b7f4SStefano Zampini           }
3586fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35876080607fSStefano Zampini             ierr = 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);CHKERRQ(ierr);
3588fd14bc51SStefano Zampini           }
3589bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35901ae86dd6SStefano Zampini             PetscInt j,k;
359108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35921ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35931ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35941ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
359508122e43SStefano Zampini               }
359608122e43SStefano Zampini             }
359708122e43SStefano Zampini           } else {
3598580bdb30SBarry Smith             ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3599580bdb30SBarry Smith             ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
360008122e43SStefano Zampini           }
360108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
360208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36039d54b7f4SStefano 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));
360408122e43SStefano Zampini #else
36059d54b7f4SStefano 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));
360608122e43SStefano Zampini #endif
360743371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
360808122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
360908122e43SStefano Zampini           B_neigs += B_neigs2;
361008122e43SStefano Zampini         }
361108122e43SStefano Zampini         if (B_ierr) {
36126c4ed002SBarry 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);
36136c4ed002SBarry 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);
36146c4ed002SBarry 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);
361508122e43SStefano Zampini         }
3616fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3617ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
361808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
361908122e43SStefano Zampini             if (eigs[j] == 0.0) {
3620ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
362108122e43SStefano Zampini             } else {
36229d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3623ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
36249d54b7f4SStefano Zampini               } else {
36259d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
36269d54b7f4SStefano Zampini               }
3627fd14bc51SStefano Zampini             }
362808122e43SStefano Zampini           }
362908122e43SStefano Zampini         }
3630bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3631aff50787SStefano Zampini     }
36326c3e6151SStefano Zampini     /* change the basis back to the original one */
36336c3e6151SStefano Zampini     if (sub_schurs->change) {
363472b8c272SStefano Zampini       Mat change,phi,phit;
36356c3e6151SStefano Zampini 
363603dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
36376c3e6151SStefano Zampini         PetscInt ii;
36386c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
36396c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36406c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3641684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3642684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3643684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3644684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3645684229deSStefano Zampini #else
36466c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3647684229deSStefano Zampini #endif
36486c3e6151SStefano Zampini           }
36496c3e6151SStefano Zampini         }
36506c3e6151SStefano Zampini       }
365172b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
36526c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
365372b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
36546c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
36556c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
36566c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
36576c3e6151SStefano Zampini     }
36588bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36598bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36609162d606SStefano Zampini     if (B_neigs) {
3661580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size);CHKERRQ(ierr);
3662fd14bc51SStefano Zampini 
3663fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36649552c7c7SStefano Zampini         PetscInt ii;
36659552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3666ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36679552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3668ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3669ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3670ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3671ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3672ac47001eSStefano Zampini #else
3673ac47001eSStefano 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);
3674ac47001eSStefano Zampini #endif
36759552c7c7SStefano Zampini           }
36769552c7c7SStefano Zampini         }
3677fd14bc51SStefano Zampini       }
3678580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size);CHKERRQ(ierr);
36799162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36809162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36819162d606SStefano Zampini       cum++;
368208122e43SStefano Zampini     }
368308122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
368408122e43SStefano Zampini     /* shift for next computation */
368508122e43SStefano Zampini     cumarray += subset_size*subset_size;
368608122e43SStefano Zampini   }
3687fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3688fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3689fd14bc51SStefano Zampini   }
369008122e43SStefano Zampini 
369108122e43SStefano Zampini   if (mss) {
369208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
369308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3694f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3695f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3696f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
369708122e43SStefano Zampini   }
3698f6f667cfSStefano Zampini   if (allocated_S_St) {
3699f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3700f6f667cfSStefano Zampini   }
3701f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
370208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
370308122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
370408122e43SStefano Zampini #endif
370508122e43SStefano Zampini   if (pcbddc->dbg_flag) {
37061b968477SStefano Zampini     PetscInt maxneigs_r;
3707b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
37086080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %D\n",maxneigs_r);CHKERRQ(ierr);
370908122e43SStefano Zampini   }
371043371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
371108122e43SStefano Zampini   PetscFunctionReturn(0);
371208122e43SStefano Zampini }
3713b1b3d7a2SStefano Zampini 
3714c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3715c8587f34SStefano Zampini {
37168629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3717c8587f34SStefano Zampini   PetscErrorCode ierr;
3718c8587f34SStefano Zampini 
3719c8587f34SStefano Zampini   PetscFunctionBegin;
3720f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
37215e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3722c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3723c8587f34SStefano Zampini 
3724684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
37250fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3726684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3727c8587f34SStefano Zampini 
37288629588bSStefano Zampini   /*
37298629588bSStefano Zampini      Setup local correction and local part of coarse basis.
37308629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
37318629588bSStefano Zampini   */
373247f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
37338629588bSStefano Zampini 
37348629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
37358629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
37368629588bSStefano Zampini 
37378629588bSStefano Zampini   /* free */
37388629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3739c8587f34SStefano Zampini   PetscFunctionReturn(0);
3740c8587f34SStefano Zampini }
3741c8587f34SStefano Zampini 
3742674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3743674ae819SStefano Zampini {
3744674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3745674ae819SStefano Zampini   PetscErrorCode ierr;
3746674ae819SStefano Zampini 
3747674ae819SStefano Zampini   PetscFunctionBegin;
3748674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
374930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3750674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3751785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3752674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3753f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3754f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3755785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
375663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
375763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3758674ae819SStefano Zampini   PetscFunctionReturn(0);
3759674ae819SStefano Zampini }
3760674ae819SStefano Zampini 
3761674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3762674ae819SStefano Zampini {
3763674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37644f1b2e48SStefano Zampini   PetscInt       i;
3765674ae819SStefano Zampini   PetscErrorCode ierr;
3766674ae819SStefano Zampini 
3767674ae819SStefano Zampini   PetscFunctionBegin;
37681e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
37691e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3770a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3771b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3772674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
377316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
37741dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3775674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3776669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3777fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
37789326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
37794f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37804f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
37814f1b2e48SStefano Zampini   }
3782e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37834f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3784e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3785c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37868af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37871c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3788674ae819SStefano Zampini   PetscFunctionReturn(0);
3789674ae819SStefano Zampini }
3790674ae819SStefano Zampini 
3791674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3792674ae819SStefano Zampini {
3793674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3794674ae819SStefano Zampini   PetscErrorCode ierr;
3795674ae819SStefano Zampini 
3796674ae819SStefano Zampini   PetscFunctionBegin;
3797674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
379858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3799ca92afb2SStefano Zampini     PetscScalar *array;
380006656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
380106656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
380258da7f69SStefano Zampini   }
3803674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3804674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
380515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
380615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3807674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3808674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3809674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
381006656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3811674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3812674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38138ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3814674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3815674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3816674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38179326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
38189326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
38199326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3820f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3821727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
38220e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3823f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
382470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
382581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
38260369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
38271dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
38284f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
38298b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3830ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3831ca92afb2SStefano Zampini     PetscInt i;
3832ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3833ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3834ca92afb2SStefano Zampini     }
3835ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3836ca92afb2SStefano Zampini   }
38374f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3838674ae819SStefano Zampini   PetscFunctionReturn(0);
3839674ae819SStefano Zampini }
3840674ae819SStefano Zampini 
3841f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
38426bfb1811SStefano Zampini {
38436bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38446bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
38456bfb1811SStefano Zampini   VecType        impVecType;
38464f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
38476bfb1811SStefano Zampini   PetscErrorCode ierr;
38486bfb1811SStefano Zampini 
38496bfb1811SStefano Zampini   PetscFunctionBegin;
38504f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3851b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
38526bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3853e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3854e7b262bdSStefano Zampini   /* R nodes */
3855e7b262bdSStefano Zampini   old_size = -1;
3856e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3857e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3858e7b262bdSStefano Zampini   }
3859e7b262bdSStefano Zampini   if (n_R != old_size) {
3860e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3861e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38626bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
38636bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
38646bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
38656bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3866e7b262bdSStefano Zampini   }
3867e7b262bdSStefano Zampini   /* local primal dofs */
3868e7b262bdSStefano Zampini   old_size = -1;
3869e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3870e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3871e7b262bdSStefano Zampini   }
3872e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3873e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
387483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3875e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
38766bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3877e7b262bdSStefano Zampini   }
3878e7b262bdSStefano Zampini   /* local explicit constraints */
3879e7b262bdSStefano Zampini   old_size = -1;
3880e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3881e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3882e7b262bdSStefano Zampini   }
3883e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3884e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
388583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
388683b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
388783b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
388883b7ccabSStefano Zampini   }
38896bfb1811SStefano Zampini   PetscFunctionReturn(0);
38906bfb1811SStefano Zampini }
38916bfb1811SStefano Zampini 
389247f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
389388ebb749SStefano Zampini {
389425084f0cSStefano Zampini   PetscErrorCode  ierr;
389525084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
389688ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
389788ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3898d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
389925084f0cSStefano Zampini   /* submatrices of local problem */
390080677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
390106656605SStefano Zampini   /* submatrices of local coarse problem */
390206656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
390325084f0cSStefano Zampini   /* working matrices */
390406656605SStefano Zampini   Mat             C_CR;
390525084f0cSStefano Zampini   /* additional working stuff */
390606656605SStefano Zampini   PC              pc_R;
3907c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
39085cbda25cSStefano Zampini   Vec             dummy_vec;
39097ebab0bbSStefano Zampini   PetscBool       isLU,isCHOL,need_benign_correction,sparserhs;
391025084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
391106656605SStefano Zampini   PetscScalar     *work;
391206656605SStefano Zampini   PetscInt        *idx_V_B;
3913ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
391406656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
391506656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
391688ebb749SStefano Zampini 
391788ebb749SStefano Zampini   PetscFunctionBegin;
39189a962809SStefano 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");
391943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
3920ffd830a3SStefano Zampini 
3921ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3922b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39234f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3924b371cd4fSStefano Zampini   n_B = pcis->n_B;
3925b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
392688ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
392788ebb749SStefano Zampini 
392888ebb749SStefano Zampini   /* vertices in boundary numbering */
3929785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
39300e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
39316080607fSStefano Zampini   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",n_vertices,i);
393288ebb749SStefano Zampini 
393306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3934019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
393506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
393606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
393706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
393806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
393906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
394006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
394106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
394206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
394306656605SStefano Zampini 
394406656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
394506656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
39462958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
394706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
394806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3949ffd830a3SStefano Zampini   lda_rhs = n_R;
3950a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
39517ebab0bbSStefano Zampini   if (isLU || isCHOL) {
395206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3953b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3954df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3955d62866d3SStefano Zampini     MatFactorType      type;
3956d62866d3SStefano Zampini 
3957df4d28bfSStefano Zampini     F = reuse_solver->F;
39586816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3959d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
39607ebab0bbSStefano Zampini     if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE;
3961ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
396222db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
39637ebab0bbSStefano Zampini   } else F = NULL;
396406656605SStefano Zampini 
3965c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3966c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3967c58f9fdbSStefano Zampini   if (F) {
3968ea799195SBarry Smith     MatSolverType solver;
3969c58f9fdbSStefano Zampini 
39703ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3971c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3972c58f9fdbSStefano Zampini   }
3973c58f9fdbSStefano Zampini 
3974ffd830a3SStefano Zampini   /* allocate workspace */
3975ffd830a3SStefano Zampini   n = 0;
3976ffd830a3SStefano Zampini   if (n_constraints) {
3977ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3978ffd830a3SStefano Zampini   }
3979ffd830a3SStefano Zampini   if (n_vertices) {
3980ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3981ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3982ffd830a3SStefano Zampini   }
39832a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39842a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39852a3a6641Sstefano_zampini   }
3986ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3987ffd830a3SStefano Zampini 
39885cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39895cbda25cSStefano Zampini   dummy_vec = NULL;
39905cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
3991c72cccf8SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec);CHKERRQ(ierr);
3992c72cccf8SStefano Zampini     ierr = VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE);CHKERRQ(ierr);
3993c72cccf8SStefano Zampini     ierr = VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name);CHKERRQ(ierr);
39945cbda25cSStefano Zampini   }
39955cbda25cSStefano Zampini 
39967ebab0bbSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
39977ebab0bbSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
39987ebab0bbSStefano Zampini 
399988ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
400088ebb749SStefano Zampini   if (n_constraints) {
4001837cedc9SStefano Zampini     Mat         M3,C_B;
400206656605SStefano Zampini     IS          is_aux;
400380677318SStefano Zampini     PetscScalar *array,*array2;
400406656605SStefano Zampini 
400525084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
400625084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
40077dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
40087dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
400988ebb749SStefano Zampini 
401080677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
401180677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
4012c58f9fdbSStefano Zampini     if (!sparserhs) {
4013580bdb30SBarry Smith       ierr = PetscArrayzero(work,lda_rhs*n_constraints);CHKERRQ(ierr);
401488ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
401506656605SStefano Zampini         const PetscScalar *row_cmat_values;
401606656605SStefano Zampini         const PetscInt    *row_cmat_indices;
401706656605SStefano Zampini         PetscInt          size_of_constraint,j;
401888ebb749SStefano Zampini 
401906656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402006656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
4021ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
402206656605SStefano Zampini         }
402306656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402406656605SStefano Zampini       }
4025c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
4026c58f9fdbSStefano Zampini     } else {
4027c58f9fdbSStefano Zampini       Mat tC_CR;
4028c58f9fdbSStefano Zampini 
4029c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4030c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
4031c58f9fdbSStefano Zampini         PetscScalar *aa;
4032c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
4033c58f9fdbSStefano Zampini         PetscBool   done;
4034c58f9fdbSStefano Zampini 
4035c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
403613903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4037c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
4038c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
4039c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
404013903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4041c58f9fdbSStefano Zampini       } else {
4042c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
4043c58f9fdbSStefano Zampini         tC_CR = C_CR;
4044c58f9fdbSStefano Zampini       }
4045c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
4046c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
4047c58f9fdbSStefano Zampini     }
4048ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
404906656605SStefano Zampini     if (F) {
4050a3df083aSStefano Zampini       if (need_benign_correction) {
4051df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4052a3df083aSStefano Zampini 
405372b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
4054580bdb30SBarry Smith         ierr = PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n);CHKERRQ(ierr);
4055a3df083aSStefano Zampini       }
4056c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
4057a3df083aSStefano Zampini       if (need_benign_correction) {
4058a3df083aSStefano Zampini         PetscScalar        *marr;
4059df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4060a3df083aSStefano Zampini 
4061a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
40625cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40635cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40645cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40655cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40665cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40675cbda25cSStefano Zampini           }
40685cbda25cSStefano Zampini         } else {
4069a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
4070a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40715cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4072a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4073a3df083aSStefano Zampini           }
40745cbda25cSStefano Zampini         }
4075a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
4076a3df083aSStefano Zampini       }
407706656605SStefano Zampini     } else {
407880677318SStefano Zampini       PetscScalar *marr;
407980677318SStefano Zampini 
408080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
408106656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
4082ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4083ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
408406656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4085c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
408606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
408706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
408806656605SStefano Zampini       }
408980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
409006656605SStefano Zampini     }
4091c58f9fdbSStefano Zampini     if (sparserhs) {
4092c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4093c58f9fdbSStefano Zampini     }
4094c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
409580677318SStefano Zampini     if (!pcbddc->switch_static) {
409680677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
409780677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
409880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
409980677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4100ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
410180677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
410280677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
410380677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
410480677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
410580677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
410680677318SStefano Zampini       }
410780677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
410880677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
410972b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
411080677318SStefano Zampini     } else {
4111ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4112ffd830a3SStefano Zampini         IS dummy;
4113ffd830a3SStefano Zampini 
4114ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
41157dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
4116ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
4117ffd830a3SStefano Zampini       } else {
411880677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
411980677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4120ffd830a3SStefano Zampini       }
412125084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
412280677318SStefano Zampini     }
412380677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
412480677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
412580677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
412680677318SStefano Zampini     if (isCHOL) {
412780677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
412880677318SStefano Zampini     } else {
412925084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
413080677318SStefano Zampini     }
4131837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
413280677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
4133837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
413472b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
4135837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
4136837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
4137f4ddd8eeSStefano Zampini   }
4138fc227af8SStefano Zampini 
4139fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
414088ebb749SStefano Zampini   if (n_vertices) {
41417ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41427ebab0bbSStefano Zampini     PetscBool oldpin;
41437ebab0bbSStefano Zampini #endif
41447ebab0bbSStefano Zampini     PetscBool isaij;
414506656605SStefano Zampini     IS        is_aux;
41463a50541eSStefano Zampini 
4147b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
41486816873aSStefano Zampini       IS tis;
41496816873aSStefano Zampini 
41506816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
41516816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
41526816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
41536816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
41546816873aSStefano Zampini     } else {
41553a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
41566816873aSStefano Zampini     }
41577ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4158*b470e4b4SRichard Tran Mills     oldpin = pcbddc->local_mat->boundtocpu;
41597ebab0bbSStefano Zampini #endif
4160*b470e4b4SRichard Tran Mills     ierr = MatBindToCPU(pcbddc->local_mat,PETSC_TRUE);CHKERRQ(ierr);
41617dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
41627dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
41637ebab0bbSStefano Zampini     ierr = PetscObjectBaseTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isaij);CHKERRQ(ierr);
41647ebab0bbSStefano Zampini     if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */
4165c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
41667ebab0bbSStefano Zampini     }
41677dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
41687ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4169*b470e4b4SRichard Tran Mills     ierr = MatBindToCPU(pcbddc->local_mat,oldpin);CHKERRQ(ierr);
41707ebab0bbSStefano Zampini #endif
417125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
417288ebb749SStefano Zampini   }
417388ebb749SStefano Zampini 
417488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4175f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
417606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
417706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
417806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
417906656605SStefano Zampini     }
4180f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
418106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
418206656605SStefano Zampini       PetscScalar *marray;
418306656605SStefano Zampini 
418406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
418506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4186f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4187f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4188f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4189f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4190f4ddd8eeSStefano Zampini     }
4191f4ddd8eeSStefano Zampini   }
419206656605SStefano Zampini 
4193f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4194a6e023c1Sstefano_zampini     PetscScalar *marr;
419588ebb749SStefano Zampini 
4196a6e023c1Sstefano_zampini     /* memory size */
419706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4198a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4199a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4200a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4201a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4202a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
42038eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4204a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4205a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
420688ebb749SStefano Zampini     }
42073301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4208a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4209a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
42108eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4211a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
421288ebb749SStefano Zampini       }
421388ebb749SStefano Zampini     } else {
4214c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4215c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
42161b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4217c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4218c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4219c0553b1fSStefano Zampini       }
422088ebb749SStefano Zampini     }
422106656605SStefano Zampini   }
4222019a44ceSStefano Zampini 
422306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
42244f1b2e48SStefano Zampini   p0_lidx_I = NULL;
42254f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4226d12edf2fSStefano Zampini     const PetscInt *idxs;
4227d12edf2fSStefano Zampini 
4228d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
42294f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
42304f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
42314f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
42324f1b2e48SStefano Zampini     }
4233d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4234d12edf2fSStefano Zampini   }
4235d16cbb6bSStefano Zampini 
423606656605SStefano Zampini   /* vertices */
423706656605SStefano Zampini   if (n_vertices) {
4238c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
423916f15bc4SStefano Zampini 
4240af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
424104708bb6SStefano Zampini 
424216f15bc4SStefano Zampini     if (n_R) {
424314393ed6SStefano Zampini       Mat               A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
424406656605SStefano Zampini       PetscBLASInt      B_N,B_one = 1;
42451683a169SBarry Smith       const PetscScalar *x;
42461683a169SBarry Smith       PetscScalar       *y;
424706656605SStefano Zampini 
424821eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
424914393ed6SStefano Zampini       if (need_benign_correction) {
425014393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
425114393ed6SStefano Zampini         IS                     is_p0;
425214393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
425314393ed6SStefano Zampini 
425414393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
425514393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
425614393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
42576080607fSStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %D != %D",n,pcbddc->benign_n);
425814393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
425914393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
42607dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
426114393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
426214393ed6SStefano Zampini       }
426314393ed6SStefano Zampini 
4264c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4265c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4266ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4267af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4268ffd830a3SStefano Zampini         } else {
4269ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4270ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4271ca92afb2SStefano Zampini           PetscInt       n;
4272ca92afb2SStefano Zampini           PetscBool      flg_row;
4273ffd830a3SStefano Zampini 
4274ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4275580bdb30SBarry Smith           ierr = PetscArrayzero(array,lda_rhs*n_vertices);CHKERRQ(ierr);
42769d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4277ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4278ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4279ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4280ca92afb2SStefano Zampini             PetscInt j;
4281ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4282ffd830a3SStefano Zampini           }
4283ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4284ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4285ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4286ffd830a3SStefano Zampini         }
4287a3df083aSStefano Zampini         if (need_benign_correction) {
4288df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4289a3df083aSStefano Zampini           PetscScalar        *marr;
4290a3df083aSStefano Zampini 
4291a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
429214393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
429314393ed6SStefano Zampini 
429414393ed6SStefano Zampini                  | 0 0  0 | (V)
429514393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
429614393ed6SStefano Zampini                  | 0 0 -1 | (p0)
429714393ed6SStefano Zampini 
429814393ed6SStefano Zampini           */
4299df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
430014393ed6SStefano Zampini             const PetscScalar *vals;
430114393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
430214393ed6SStefano Zampini             PetscInt          n,j,nz;
430314393ed6SStefano Zampini 
4304df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4305df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
430614393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
430714393ed6SStefano Zampini             for (j=0;j<n;j++) {
430814393ed6SStefano Zampini               PetscScalar val = vals[j];
430914393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
431014393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
431114393ed6SStefano Zampini             }
431214393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4313df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
431414393ed6SStefano Zampini           }
431572b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
431672b8c272SStefano Zampini         }
4317c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4318c58f9fdbSStefano Zampini         Brhs = A_RV;
4319c58f9fdbSStefano Zampini       } else {
4320c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4321c58f9fdbSStefano Zampini 
4322c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4323fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4324c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4325c58f9fdbSStefano Zampini         } else {
4326c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4327c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4328c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4329c58f9fdbSStefano Zampini           A_RVT = A_VR;
4330c58f9fdbSStefano Zampini         }
4331c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4332c58f9fdbSStefano Zampini           PetscScalar *aa;
4333c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4334c58f9fdbSStefano Zampini           PetscBool   done;
4335c58f9fdbSStefano Zampini 
4336c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
433713903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4338c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4339c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4340c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
434113903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4342c58f9fdbSStefano Zampini         } else {
4343c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4344c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4345c58f9fdbSStefano Zampini         }
4346c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4347c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4348c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4349c58f9fdbSStefano Zampini       }
435072b8c272SStefano Zampini       if (F) {
435114393ed6SStefano Zampini         /* need to correct the rhs */
435272b8c272SStefano Zampini         if (need_benign_correction) {
435372b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
435472b8c272SStefano Zampini           PetscScalar        *marr;
435572b8c272SStefano Zampini 
4356c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
43575cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43585cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43595cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43605cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
43615cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43625cbda25cSStefano Zampini             }
43635cbda25cSStefano Zampini           } else {
4364a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4365a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43665cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4367a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4368a3df083aSStefano Zampini             }
43695cbda25cSStefano Zampini           }
4370c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4371a3df083aSStefano Zampini         }
4372c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4373c58f9fdbSStefano Zampini         if (restoreavr) {
4374c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4375c58f9fdbSStefano Zampini         }
437614393ed6SStefano Zampini         /* need to correct the solution */
4377a3df083aSStefano Zampini         if (need_benign_correction) {
4378df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4379a3df083aSStefano Zampini           PetscScalar        *marr;
4380a3df083aSStefano Zampini 
4381a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
43825cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43835cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43845cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43855cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
43865cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43875cbda25cSStefano Zampini             }
43885cbda25cSStefano Zampini           } else {
4389a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4390a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43915cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4392a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4393a3df083aSStefano Zampini             }
43945cbda25cSStefano Zampini           }
4395a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4396a3df083aSStefano Zampini         }
439706656605SStefano Zampini       } else {
4398c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
439906656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4400ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4401ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
440206656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4403c0decd05SBarry Smith           ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
440406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
440506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
440606656605SStefano Zampini         }
4407c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
440806656605SStefano Zampini       }
440980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4410c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4411ffd830a3SStefano Zampini       /* S_VV and S_CV */
441206656605SStefano Zampini       if (n_constraints) {
441306656605SStefano Zampini         Mat B;
441480677318SStefano Zampini 
4415580bdb30SBarry Smith         ierr = PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices);CHKERRQ(ierr);
441680677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4417ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4418ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
441980677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442080677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442180677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
442280677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
442380677318SStefano Zampini         }
4424ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
442580677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
442680677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4427ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
442880677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
442906656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4430ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4431ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
443206656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
443306656605SStefano Zampini       }
4434ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4435ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4436ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4437ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4438ffd830a3SStefano Zampini       }
443906656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
444014393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
444114393ed6SStefano Zampini       if (need_benign_correction) {
4442df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
444314393ed6SStefano Zampini         PetscScalar      *marr,*sums;
444414393ed6SStefano Zampini 
444514393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4446f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4447df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
444814393ed6SStefano Zampini           const PetscScalar *vals;
444914393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
445014393ed6SStefano Zampini           PetscInt          n,j,nz;
445114393ed6SStefano Zampini 
4452df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4453df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
445414393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
445514393ed6SStefano Zampini             PetscInt k;
445614393ed6SStefano Zampini             sums[j] = 0.;
445714393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
445814393ed6SStefano Zampini           }
445914393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
446014393ed6SStefano Zampini           for (j=0;j<n;j++) {
446114393ed6SStefano Zampini             PetscScalar val = vals[j];
446214393ed6SStefano Zampini             PetscInt k;
446314393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
446414393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
446514393ed6SStefano Zampini             }
446614393ed6SStefano Zampini           }
446714393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4468df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
446914393ed6SStefano Zampini         }
447014393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4471f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
447214393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
447314393ed6SStefano Zampini       }
447480677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
447506656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
44761683a169SBarry Smith       ierr = MatDenseGetArrayRead(A_VV,&x);CHKERRQ(ierr);
447706656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
447806656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
44791683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(A_VV,&x);CHKERRQ(ierr);
448006656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
448106656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4482d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4483019a44ceSStefano Zampini     } else {
4484d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4485d16cbb6bSStefano Zampini     }
448621eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4487d16cbb6bSStefano Zampini 
448806656605SStefano Zampini     /* coarse basis functions */
448906656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
449016f15bc4SStefano Zampini       PetscScalar *y;
449116f15bc4SStefano Zampini 
4492ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
449306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
449406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
449506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449706656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
449806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
449906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
450006656605SStefano Zampini 
450106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45024f1b2e48SStefano Zampini         PetscInt j;
45034f1b2e48SStefano Zampini 
450406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
450506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
450606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
45094f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
451006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
451106656605SStefano Zampini       }
451206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
451306656605SStefano Zampini     }
451404708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
451504708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
451606656605SStefano Zampini   }
45175cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
451806656605SStefano Zampini 
451906656605SStefano Zampini   if (n_constraints) {
452006656605SStefano Zampini     Mat B;
452106656605SStefano Zampini 
4522ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
452306656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
452480677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
452506656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
452606656605SStefano Zampini     if (n_vertices) {
452703dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
452880677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
452980677318SStefano Zampini       } else {
453080677318SStefano Zampini         Mat S_VCt;
453180677318SStefano Zampini 
4532ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4533ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
453472b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4535ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4536ffd830a3SStefano Zampini         }
453780677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
453880677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
453980677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
454080677318SStefano Zampini       }
454106656605SStefano Zampini     }
454206656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
454306656605SStefano Zampini     /* coarse basis functions */
454406656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
454506656605SStefano Zampini       PetscScalar *y;
454606656605SStefano Zampini 
4547ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
454806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
454906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
455006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
455106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
455206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
455306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
455406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45554f1b2e48SStefano Zampini         PetscInt j;
45564f1b2e48SStefano Zampini 
455706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
455806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
455906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
456006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
456106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
45624f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
456306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
456406656605SStefano Zampini       }
456506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
456606656605SStefano Zampini     }
456706656605SStefano Zampini   }
456880677318SStefano Zampini   if (n_constraints) {
456980677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
457080677318SStefano Zampini   }
45714f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
457272b8c272SStefano Zampini 
457372b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
457472b8c272SStefano Zampini   if (pcbddc->benign_n) {
457572b8c272SStefano Zampini     Mat               B0_B,B0_BPHI;
457672b8c272SStefano Zampini     IS                is_dummy;
45771683a169SBarry Smith     const PetscScalar *data;
457872b8c272SStefano Zampini     PetscInt          j;
457972b8c272SStefano Zampini 
458072b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
45817dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
458272b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
458372b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
458486c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
45851683a169SBarry Smith     ierr = MatDenseGetArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
458672b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
458772b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
458872b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
458972b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
459072b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
459172b8c272SStefano Zampini       }
459272b8c272SStefano Zampini     }
45931683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
459472b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
459572b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
459672b8c272SStefano Zampini   }
4597019a44ceSStefano Zampini 
459806656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
45993301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4600ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4601ffd830a3SStefano Zampini     PetscScalar *marray;
460206656605SStefano Zampini 
460306656605SStefano Zampini     if (n_constraints) {
4604ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
460506656605SStefano Zampini 
4606abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
460706656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4608ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
460916f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
461006656605SStefano Zampini       if (n_vertices) {
4611ffd830a3SStefano Zampini         Mat S_VCT;
461206656605SStefano Zampini 
461306656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4614ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
461516f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
461606656605SStefano Zampini       }
4617ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
46185b782168SStefano Zampini     } else {
46195b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
462006656605SStefano Zampini     }
462116f15bc4SStefano Zampini     if (n_vertices && n_R) {
4622ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4623ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4624ffd830a3SStefano Zampini       PetscInt       n;
4625ffd830a3SStefano Zampini       PetscBool      flg_row;
462606656605SStefano Zampini 
4627ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4628af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4629ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4630ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4631ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4632ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4633ffd830a3SStefano Zampini         PetscInt j;
4634ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4635ffd830a3SStefano Zampini       }
4636ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4637ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4638ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
463906656605SStefano Zampini     }
464006656605SStefano Zampini 
4641ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4642abc8f43dSstefano_zampini     if (n_vertices) {
4643ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4644ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4645ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4646ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
464706656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4648c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
464906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
465006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
465106656605SStefano Zampini       }
4652ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4653abc8f43dSstefano_zampini     }
46545b782168SStefano Zampini     if (B_C) {
4655ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4656ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4657ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4658ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4659ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4660c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
4661ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4662ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
466306656605SStefano Zampini       }
4664ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
46655b782168SStefano Zampini     }
466606656605SStefano Zampini     /* coarse basis functions */
466706656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
466806656605SStefano Zampini       PetscScalar *y;
466906656605SStefano Zampini 
4670ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
467106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
467206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
467306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
467406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
467506656605SStefano Zampini       if (i<n_vertices) {
467606656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
467706656605SStefano Zampini       }
467806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
467906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
468006656605SStefano Zampini 
468106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
468206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
468306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
468406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
468506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
468606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
468706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
468806656605SStefano Zampini       }
468906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
469006656605SStefano Zampini     }
4691ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4692ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
469306656605SStefano Zampini   }
4694a6e023c1Sstefano_zampini 
4695d62866d3SStefano Zampini   /* free memory */
469688ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
469706656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
469806656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
469906656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
470006656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4701d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4702d62866d3SStefano Zampini   if (n_vertices) {
4703d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4704d62866d3SStefano Zampini   }
4705d62866d3SStefano Zampini   if (n_constraints) {
4706d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4707d62866d3SStefano Zampini   }
47088ead10e4SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
47098ead10e4SStefano Zampini 
471088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
471188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
471288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4713d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
471488ebb749SStefano Zampini     Mat         coarse_sub_mat;
471525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
471688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
471788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
471888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
47198bec7fa6SStefano Zampini     Mat         C_B,CPHI;
47208bec7fa6SStefano Zampini     IS          is_dummy;
47218bec7fa6SStefano Zampini     Vec         mones;
472288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
472388ebb749SStefano Zampini     PetscReal   real_value;
472488ebb749SStefano Zampini 
4725a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4726a3df083aSStefano Zampini       Mat A;
4727a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
47287dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
47297dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
47307dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
47317dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4732a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4733a3df083aSStefano Zampini     } else {
473488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
473588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
473688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
473788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4738a3df083aSStefano Zampini     }
473988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
474088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4741ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
474288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
474388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
474488ebb749SStefano Zampini     }
474588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
474688ebb749SStefano Zampini 
474725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47483301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
474925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4750ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
475188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
475388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
475488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
475688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
475788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
475988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
476088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
476188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
476288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
476388ebb749SStefano Zampini     } else {
476488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
476588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
476688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
476788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
476888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
476988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
477088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
477188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
477288ebb749SStefano Zampini     }
477388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
477488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
477588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4776511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
47774f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4778fc227af8SStefano Zampini       Mat               B0_B,B0_BPHI;
47791683a169SBarry Smith       const PetscScalar *data2;
47801683a169SBarry Smith       PetscScalar       *data;
47814f1b2e48SStefano Zampini       PetscInt          j;
4782d12edf2fSStefano Zampini 
47834f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
47847dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4785d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
478686c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4787d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
47881683a169SBarry Smith       ierr = MatDenseGetArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
47894f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
47904f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4791d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
47924f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
47934f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
47944f1b2e48SStefano Zampini         }
4795d12edf2fSStefano Zampini       }
4796d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
47971683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
4798d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4799d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4800d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4801d12edf2fSStefano Zampini     }
4802d12edf2fSStefano Zampini #if 0
4803d12edf2fSStefano Zampini   {
4804d12edf2fSStefano Zampini     PetscViewer viewer;
4805d12edf2fSStefano Zampini     char filename[256];
4806ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4807d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4808a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4809ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4810ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4811ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4812d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4813a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4814ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4815ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
481672b8c272SStefano Zampini     }
4817ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4818ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4819ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4820ffd830a3SStefano Zampini     }
4821ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4822ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4823ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4824ffd830a3SStefano Zampini     }
482572b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4826ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4827ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4828ffd830a3SStefano Zampini     }
4829fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4830fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4831fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4832fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4833fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4834fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4835fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4836fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4837fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4838fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4839d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4840d12edf2fSStefano Zampini   }
4841d12edf2fSStefano Zampini #endif
484281d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
48438bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
48441575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
484506656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
48468bec7fa6SStefano Zampini 
48478bec7fa6SStefano Zampini     /* check constraints */
4848a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
48497dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
48504f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
48518bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4852a00504b5SStefano Zampini     } else {
4853a00504b5SStefano Zampini       PetscScalar *data;
4854a00504b5SStefano Zampini       Mat         tmat;
4855a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4856a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4857a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4858a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4859a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4860a00504b5SStefano Zampini     }
48618bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
48628bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
48638bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
48648bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4865bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4866ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4867bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4868bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4869bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4870bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4871bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
487288ebb749SStefano Zampini     }
48738bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
48748bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
48758bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
48768bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
487725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
487888ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
487988ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
488088ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
488188ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
488288ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
488388ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
488488ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
488588ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
488688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
488788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4888ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
488988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
489088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
489188ebb749SStefano Zampini     }
489288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
489388ebb749SStefano Zampini   }
48947ebab0bbSStefano Zampini   /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */
48957ebab0bbSStefano Zampini   {
48967ebab0bbSStefano Zampini     PetscBool gpu;
48977ebab0bbSStefano Zampini 
48987ebab0bbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcis->vec1_N,VECSEQCUDA,&gpu);CHKERRQ(ierr);
48997ebab0bbSStefano Zampini     if (gpu) {
49007ebab0bbSStefano Zampini       if (pcbddc->local_auxmat1) {
49017ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->local_auxmat1,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat1);CHKERRQ(ierr);
49027ebab0bbSStefano Zampini       }
49037ebab0bbSStefano Zampini       if (pcbddc->local_auxmat2) {
49047ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->local_auxmat2,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
49057ebab0bbSStefano Zampini       }
49067ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_B) {
49077ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_phi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
49087ebab0bbSStefano Zampini       }
49097ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_D) {
49107ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_phi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
49117ebab0bbSStefano Zampini       }
49127ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_B) {
49137ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
49147ebab0bbSStefano Zampini       }
49157ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_D) {
49167ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
49177ebab0bbSStefano Zampini       }
49187ebab0bbSStefano Zampini     }
49197ebab0bbSStefano Zampini   }
49208629588bSStefano Zampini   /* get back data */
49218629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
492288ebb749SStefano Zampini   PetscFunctionReturn(0);
492388ebb749SStefano Zampini }
492488ebb749SStefano Zampini 
49257dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4926aa0d41d4SStefano Zampini {
4927d65f70fdSStefano Zampini   Mat            *work_mat;
4928d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4929d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4930c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4931aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4932aa0d41d4SStefano Zampini 
4933aa0d41d4SStefano Zampini   PetscFunctionBegin;
4934d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4935d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4936d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4937d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4938aa0d41d4SStefano Zampini 
4939d65f70fdSStefano Zampini   if (!rsorted) {
4940906d46d4SStefano Zampini     const PetscInt *idxs;
4941906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4942aa0d41d4SStefano Zampini 
4943d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4944d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4945d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4946d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4947aa0d41d4SStefano Zampini     }
4948d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4949d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4950d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4951d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4952aa0d41d4SStefano Zampini     }
4953d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4954d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4955d65f70fdSStefano Zampini   } else {
4956d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4957d65f70fdSStefano Zampini     isrow_s = isrow;
4958aa0d41d4SStefano Zampini   }
4959906d46d4SStefano Zampini 
4960d65f70fdSStefano Zampini   if (!csorted) {
4961d65f70fdSStefano Zampini     if (isrow == iscol) {
4962d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4963d65f70fdSStefano Zampini       iscol_s = isrow_s;
4964d65f70fdSStefano Zampini     } else {
4965d65f70fdSStefano Zampini       const PetscInt *idxs;
4966d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4967906d46d4SStefano Zampini 
4968d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4969d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4970d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4971d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4972d65f70fdSStefano Zampini       }
4973d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4974d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4975d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4976d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4977d65f70fdSStefano Zampini       }
4978d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4979d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4980d65f70fdSStefano Zampini     }
4981d65f70fdSStefano Zampini   } else {
4982d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4983d65f70fdSStefano Zampini     iscol_s = iscol;
4984d65f70fdSStefano Zampini   }
4985d65f70fdSStefano Zampini 
49867dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4987d65f70fdSStefano Zampini 
4988d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4989906d46d4SStefano Zampini     Mat      new_mat;
4990d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4991906d46d4SStefano Zampini 
4992d65f70fdSStefano Zampini     if (!rsorted) {
4993d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4994d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4995d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4996d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4997906d46d4SStefano Zampini       }
4998d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4999d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
5000d65f70fdSStefano Zampini     } else {
5001d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
5002906d46d4SStefano Zampini     }
5003d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
5004d65f70fdSStefano Zampini 
5005d65f70fdSStefano Zampini     if (!csorted) {
5006d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
5007d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
5008d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
5009d65f70fdSStefano Zampini       } else {
5010d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
5011f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
5012d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
5013d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
5014d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
5015d65f70fdSStefano Zampini         }
5016d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
5017d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
5018d65f70fdSStefano Zampini       }
5019d65f70fdSStefano Zampini     } else {
5020d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
5021d65f70fdSStefano Zampini     }
5022d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
5023d65f70fdSStefano Zampini 
5024d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
5025d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
5026d65f70fdSStefano Zampini     work_mat[0] = new_mat;
5027d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
5028d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
5029d65f70fdSStefano Zampini   }
5030d65f70fdSStefano Zampini 
5031d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
5032d65f70fdSStefano Zampini   *B = work_mat[0];
5033d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
5034d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
5035d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
5036d65f70fdSStefano Zampini   PetscFunctionReturn(0);
5037d65f70fdSStefano Zampini }
5038d65f70fdSStefano Zampini 
50395e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
5040aa0d41d4SStefano Zampini {
5041aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
50425e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5043022d8d2bSstefano_zampini   Mat            new_mat,lA;
50445e8657edSStefano Zampini   IS             is_local,is_global;
5045d65f70fdSStefano Zampini   PetscInt       local_size;
5046d65f70fdSStefano Zampini   PetscBool      isseqaij;
5047aa0d41d4SStefano Zampini   PetscErrorCode ierr;
5048aa0d41d4SStefano Zampini 
5049aa0d41d4SStefano Zampini   PetscFunctionBegin;
5050aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
50515e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
50525e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
5053b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
5054aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
50557dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
5056aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
5057906d46d4SStefano Zampini 
5058906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
5059906d46d4SStefano Zampini     Vec       x,x_change;
5060906d46d4SStefano Zampini     PetscReal error;
5061906d46d4SStefano Zampini 
50625e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
5063906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
50645e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
5065e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5066e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5067d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
506888428137SStefano Zampini     if (!pcbddc->change_interior) {
506988428137SStefano Zampini       const PetscScalar *x,*y,*v;
507088428137SStefano Zampini       PetscReal         lerror = 0.;
507188428137SStefano Zampini       PetscInt          i;
507288428137SStefano Zampini 
507388428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
507488428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
507588428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
507688428137SStefano Zampini       for (i=0;i<local_size;i++)
507788428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
507888428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
507988428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
508088428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
508188428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
508288428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5083637e8532SStefano Zampini       if (error > PETSC_SMALL) {
5084637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
50856080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",error);
5086637e8532SStefano Zampini         } else {
50876080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",error);
5088637e8532SStefano Zampini         }
5089637e8532SStefano Zampini       }
509088428137SStefano Zampini     }
5091e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5092e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5093906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5094906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5095637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5096637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
50976080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
5098637e8532SStefano Zampini       } else {
50996080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",error);
5100637e8532SStefano Zampini       }
5101637e8532SStefano Zampini     }
5102906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
5103906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5104906d46d4SStefano Zampini   }
5105906d46d4SStefano Zampini 
5106022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
5107022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
5108022d8d2bSstefano_zampini 
510922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
51107ebab0bbSStefano Zampini   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
511122d5777bSStefano Zampini   if (isseqaij) {
5112a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5113a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
5114022d8d2bSstefano_zampini     if (lA) {
5115022d8d2bSstefano_zampini       Mat work;
5116022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5117022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5118022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5119022d8d2bSstefano_zampini     }
5120aa0d41d4SStefano Zampini   } else {
5121a00504b5SStefano Zampini     Mat work_mat;
51221cf9b237SStefano Zampini 
5123a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5124aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5125a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
51261d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
5127022d8d2bSstefano_zampini     if (lA) {
5128022d8d2bSstefano_zampini       Mat work;
5129022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5130022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5131022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5132022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5133022d8d2bSstefano_zampini     }
5134aa0d41d4SStefano Zampini   }
51353301b35fSStefano Zampini   if (matis->A->symmetric_set) {
51363301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
5137e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
51383301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
5139e496cd5dSStefano Zampini #endif
51403301b35fSStefano Zampini   }
5141d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
5142aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
5143aa0d41d4SStefano Zampini }
5144aa0d41d4SStefano Zampini 
51458ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
5146a64d13efSStefano Zampini {
5147a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
5148a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5149d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
515053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
51513a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
51523a50541eSStefano Zampini   PetscInt        vbs,bs;
51536816873aSStefano Zampini   PetscBT         bitmask=NULL;
5154a64d13efSStefano Zampini   PetscErrorCode  ierr;
5155a64d13efSStefano Zampini 
5156a64d13efSStefano Zampini   PetscFunctionBegin;
5157b23d619eSStefano Zampini   /*
5158b23d619eSStefano Zampini     No need to setup local scatters if
5159b23d619eSStefano Zampini       - primal space is unchanged
5160b23d619eSStefano Zampini         AND
5161b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
5162b23d619eSStefano Zampini         AND
5163b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5164b23d619eSStefano Zampini   */
5165b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5166f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5167f4ddd8eeSStefano Zampini   }
5168f4ddd8eeSStefano Zampini   /* destroy old objects */
5169f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
5170f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
5171f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
5172a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5173b371cd4fSStefano Zampini   n_B = pcis->n_B;
5174b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5175b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
51763a50541eSStefano Zampini 
5177a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
51786816873aSStefano Zampini 
517953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5180b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
5181854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
5182a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
5183a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
51840e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
5185a64d13efSStefano Zampini     }
5186a64d13efSStefano Zampini 
5187a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
51884641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
51896816873aSStefano Zampini         idx_R_local[n_R++] = i;
5190a64d13efSStefano Zampini       }
5191a64d13efSStefano Zampini     }
5192df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5193df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
51946816873aSStefano Zampini 
5195df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5196df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
51976816873aSStefano Zampini   }
51983a50541eSStefano Zampini 
51993a50541eSStefano Zampini   /* Block code */
52003a50541eSStefano Zampini   vbs = 1;
52013a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
52023a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
52033a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
52043a50541eSStefano Zampini     PetscInt  *vary;
5205b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5206785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
5207580bdb30SBarry Smith       ierr = PetscArrayzero(vary,pcis->n/bs);CHKERRQ(ierr);
5208d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5209d3df7717SStefano 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 */
52100e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5211d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
52123a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
52133a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
52143a50541eSStefano Zampini           break;
52153a50541eSStefano Zampini         }
52163a50541eSStefano Zampini       }
5217d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5218d3df7717SStefano Zampini     } else {
5219d3df7717SStefano Zampini       /* Verify directly the R set */
5220d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5221d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5222d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5223d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5224d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5225d3df7717SStefano Zampini             break;
5226d3df7717SStefano Zampini           }
5227d3df7717SStefano Zampini         }
5228d3df7717SStefano Zampini       }
5229d3df7717SStefano Zampini     }
52303a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
52313a50541eSStefano Zampini       vbs = bs;
52323a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
52333a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
52343a50541eSStefano Zampini       }
52353a50541eSStefano Zampini     }
52363a50541eSStefano Zampini   }
52373a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5238b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5239df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
524053892102SStefano Zampini 
5241df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5242df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
524353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5244df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
524553892102SStefano Zampini   } else {
52463a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
524753892102SStefano Zampini   }
5248a64d13efSStefano Zampini 
5249a64d13efSStefano Zampini   /* print some info if requested */
5250a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5251a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5252a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
52531575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5254a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
52556080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %D, dirichlet_size = %D, boundary_size = %D\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
52566080607fSStefano 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);
5257a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5258a64d13efSStefano Zampini   }
5259a64d13efSStefano Zampini 
5260a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5261b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
52626816873aSStefano Zampini     IS       is_aux1,is_aux2;
52636816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
52646816873aSStefano Zampini 
52653a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5266854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5267854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5268a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
52694641a718SStefano Zampini     for (i=0; i<n_D; i++) {
52704641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
52714641a718SStefano Zampini     }
5272a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5273a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
52744641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
52754641a718SStefano Zampini         aux_array1[j++] = i;
5276a64d13efSStefano Zampini       }
5277a64d13efSStefano Zampini     }
5278a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5279a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5280a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
52814641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
52824641a718SStefano Zampini         aux_array2[j++] = i;
5283a64d13efSStefano Zampini       }
5284a64d13efSStefano Zampini     }
5285a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5286a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
52879448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5288a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5289a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5290a64d13efSStefano Zampini 
52918eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5292785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5293a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
52944641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
52954641a718SStefano Zampini           aux_array1[j++] = i;
5296a64d13efSStefano Zampini         }
5297a64d13efSStefano Zampini       }
5298a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
52999448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5300a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5301a64d13efSStefano Zampini     }
53024641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
53033a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5304d62866d3SStefano Zampini   } else {
5305df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
53066816873aSStefano Zampini     IS                 tis;
53076816873aSStefano Zampini     PetscInt           schur_size;
53086816873aSStefano Zampini 
5309df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
53106816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
53119448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
53126816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
53136816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
53146816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
53159448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
53166816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5317d62866d3SStefano Zampini     }
5318d62866d3SStefano Zampini   }
5319a64d13efSStefano Zampini   PetscFunctionReturn(0);
5320a64d13efSStefano Zampini }
5321a64d13efSStefano Zampini 
53226d9e27e4SStefano Zampini static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B)
532392cccca0SStefano Zampini {
532492cccca0SStefano Zampini   MatNullSpace   NullSpace;
532592cccca0SStefano Zampini   Mat            dmat;
532692cccca0SStefano Zampini   const Vec      *nullvecs;
532792cccca0SStefano Zampini   Vec            v,v2,*nullvecs2;
53286d9e27e4SStefano Zampini   VecScatter     sct = NULL;
5329eb06acf8SStefano Zampini   PetscContainer c;
5330eb06acf8SStefano Zampini   PetscScalar    *ddata;
5331295df10fSStefano Zampini   PetscInt       k,nnsp_size,bsiz,bsiz2,n,N,bs;
533292cccca0SStefano Zampini   PetscBool      nnsp_has_cnst;
533392cccca0SStefano Zampini   PetscErrorCode ierr;
533492cccca0SStefano Zampini 
533592cccca0SStefano Zampini   PetscFunctionBegin;
53366d9e27e4SStefano Zampini   if (!is && !B) { /* MATIS */
53376d9e27e4SStefano Zampini     Mat_IS* matis = (Mat_IS*)A->data;
53386d9e27e4SStefano Zampini 
53396d9e27e4SStefano Zampini     if (!B) {
53406d9e27e4SStefano Zampini       ierr = MatISGetLocalMat(A,&B);CHKERRQ(ierr);
53416d9e27e4SStefano Zampini     }
53426d9e27e4SStefano Zampini     sct  = matis->cctx;
53436d9e27e4SStefano Zampini     ierr = PetscObjectReference((PetscObject)sct);CHKERRQ(ierr);
53446d9e27e4SStefano Zampini   } else {
534592cccca0SStefano Zampini     ierr = MatGetNullSpace(B,&NullSpace);CHKERRQ(ierr);
534692cccca0SStefano Zampini     if (!NullSpace) {
534792cccca0SStefano Zampini       ierr = MatGetNearNullSpace(B,&NullSpace);CHKERRQ(ierr);
534892cccca0SStefano Zampini     }
534992cccca0SStefano Zampini     if (NullSpace) PetscFunctionReturn(0);
53506d9e27e4SStefano Zampini   }
535192cccca0SStefano Zampini   ierr = MatGetNullSpace(A,&NullSpace);CHKERRQ(ierr);
535292cccca0SStefano Zampini   if (!NullSpace) {
535392cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A,&NullSpace);CHKERRQ(ierr);
535492cccca0SStefano Zampini   }
535592cccca0SStefano Zampini   if (!NullSpace) PetscFunctionReturn(0);
53566d9e27e4SStefano Zampini 
535792cccca0SStefano Zampini   ierr = MatCreateVecs(A,&v,NULL);CHKERRQ(ierr);
535892cccca0SStefano Zampini   ierr = MatCreateVecs(B,&v2,NULL);CHKERRQ(ierr);
53596d9e27e4SStefano Zampini   if (!sct) {
53609448b7f1SJunchao Zhang     ierr = VecScatterCreate(v,is,v2,NULL,&sct);CHKERRQ(ierr);
53616d9e27e4SStefano Zampini   }
536292cccca0SStefano Zampini   ierr = MatNullSpaceGetVecs(NullSpace,&nnsp_has_cnst,&nnsp_size,(const Vec**)&nullvecs);CHKERRQ(ierr);
5363295df10fSStefano Zampini   bsiz = bsiz2 = nnsp_size+!!nnsp_has_cnst;
536492cccca0SStefano Zampini   ierr = PetscMalloc1(bsiz,&nullvecs2);CHKERRQ(ierr);
536592cccca0SStefano Zampini   ierr = VecGetBlockSize(v2,&bs);CHKERRQ(ierr);
536692cccca0SStefano Zampini   ierr = VecGetSize(v2,&N);CHKERRQ(ierr);
536792cccca0SStefano Zampini   ierr = VecGetLocalSize(v2,&n);CHKERRQ(ierr);
5368eb06acf8SStefano Zampini   ierr = PetscMalloc1(n*bsiz,&ddata);CHKERRQ(ierr);
536992cccca0SStefano Zampini   for (k=0;k<nnsp_size;k++) {
5370eb06acf8SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*k,&nullvecs2[k]);CHKERRQ(ierr);
537192cccca0SStefano Zampini     ierr = VecScatterBegin(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537292cccca0SStefano Zampini     ierr = VecScatterEnd(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537392cccca0SStefano Zampini   }
537492cccca0SStefano Zampini   if (nnsp_has_cnst) {
5375eb06acf8SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*nnsp_size,&nullvecs2[nnsp_size]);CHKERRQ(ierr);
537692cccca0SStefano Zampini     ierr = VecSet(nullvecs2[nnsp_size],1.0);CHKERRQ(ierr);
537792cccca0SStefano Zampini   }
5378295df10fSStefano Zampini   ierr = PCBDDCOrthonormalizeVecs(&bsiz2,nullvecs2);CHKERRQ(ierr);
5379295df10fSStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)B),PETSC_FALSE,bsiz2,nullvecs2,&NullSpace);CHKERRQ(ierr);
5380295df10fSStefano Zampini 
5381eb06acf8SStefano Zampini   ierr = MatCreateDense(PetscObjectComm((PetscObject)B),n,PETSC_DECIDE,N,bsiz2,ddata,&dmat);CHKERRQ(ierr);
5382eb06acf8SStefano Zampini   ierr = PetscContainerCreate(PetscObjectComm((PetscObject)B),&c);CHKERRQ(ierr);
5383eb06acf8SStefano Zampini   ierr = PetscContainerSetPointer(c,ddata);CHKERRQ(ierr);
5384eb06acf8SStefano Zampini   ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
5385eb06acf8SStefano Zampini   ierr = PetscObjectCompose((PetscObject)dmat,"_PBDDC_Null_dmat_arr",(PetscObject)c);CHKERRQ(ierr);
5386eb06acf8SStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
538792cccca0SStefano Zampini   ierr = PetscObjectCompose((PetscObject)NullSpace,"_PBDDC_Null_dmat",(PetscObject)dmat);CHKERRQ(ierr);
538892cccca0SStefano Zampini   ierr = MatDestroy(&dmat);CHKERRQ(ierr);
5389eb06acf8SStefano Zampini 
539092cccca0SStefano Zampini   for (k=0;k<bsiz;k++) {
539192cccca0SStefano Zampini     ierr = VecDestroy(&nullvecs2[k]);CHKERRQ(ierr);
539292cccca0SStefano Zampini   }
539392cccca0SStefano Zampini   ierr = PetscFree(nullvecs2);CHKERRQ(ierr);
539492cccca0SStefano Zampini   ierr = MatSetNearNullSpace(B,NullSpace);CHKERRQ(ierr);
539592cccca0SStefano Zampini   ierr = MatNullSpaceDestroy(&NullSpace);CHKERRQ(ierr);
539692cccca0SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
539792cccca0SStefano Zampini   ierr = VecDestroy(&v2);CHKERRQ(ierr);
539892cccca0SStefano Zampini   ierr = VecScatterDestroy(&sct);CHKERRQ(ierr);
539992cccca0SStefano Zampini   PetscFunctionReturn(0);
540092cccca0SStefano Zampini }
5401304d26faSStefano Zampini 
5402684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5403304d26faSStefano Zampini {
5404304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5405304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5406304d26faSStefano Zampini   PC             pc_temp;
5407304d26faSStefano Zampini   Mat            A_RR;
540892cccca0SStefano Zampini   MatNullSpace   nnsp;
5409f4ddd8eeSStefano Zampini   MatReuse       reuse;
5410304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5411304d26faSStefano Zampini   PetscReal      value;
541204708bb6SStefano Zampini   PetscInt       n_D,n_R;
541392cccca0SStefano Zampini   PetscBool      issbaij,opts;
5414304d26faSStefano Zampini   PetscErrorCode ierr;
541592cccca0SStefano Zampini   void           (*f)(void) = 0;
5416312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5417e604994aSStefano Zampini   size_t         len;
5418304d26faSStefano Zampini 
5419304d26faSStefano Zampini   PetscFunctionBegin;
542043371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
54216d9e27e4SStefano Zampini   /* approximate solver, propagate NearNullSpace if needed */
54226d9e27e4SStefano Zampini   if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) {
54236d9e27e4SStefano Zampini     MatNullSpace gnnsp1,gnnsp2;
54246d9e27e4SStefano Zampini     PetscBool    lhas,ghas;
54256d9e27e4SStefano Zampini 
54266d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pcbddc->local_mat,&nnsp);CHKERRQ(ierr);
54276d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&gnnsp1);CHKERRQ(ierr);
54286d9e27e4SStefano Zampini     ierr = MatGetNullSpace(pc->pmat,&gnnsp2);CHKERRQ(ierr);
54296d9e27e4SStefano Zampini     lhas = nnsp ? PETSC_TRUE : PETSC_FALSE;
54306d9e27e4SStefano Zampini     ierr = MPIU_Allreduce(&lhas,&ghas,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
54316d9e27e4SStefano Zampini     if (!ghas && (gnnsp1 || gnnsp2)) {
54326d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pc->pmat,NULL,NULL);CHKERRQ(ierr);
54336d9e27e4SStefano Zampini     }
54346d9e27e4SStefano Zampini   }
54356d9e27e4SStefano Zampini 
5436e604994aSStefano Zampini   /* compute prefixes */
5437e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5438e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5439e604994aSStefano Zampini   if (!pcbddc->current_level) {
5440a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5441a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5442a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5443a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5444e604994aSStefano Zampini   } else {
544535529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5446e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5447e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5448312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5449312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5450a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
545134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
545234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5453a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5454a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5455a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5456a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5457e604994aSStefano Zampini   }
5458e604994aSStefano Zampini 
5459304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5460684f6988SStefano Zampini   if (dirichlet) {
5461d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5462450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
54636080607fSStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
5464450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5465a3df083aSStefano Zampini         Mat    A_IIn;
5466a3df083aSStefano Zampini 
5467a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5468a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5469a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5470a3df083aSStefano Zampini       }
5471450f8f5eSStefano Zampini     }
54723301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5473d1e098c7SStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
5474964fefecSStefano Zampini     }
5475ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5476964fefecSStefano Zampini     n_D  = pcis->n - pcis->n_B;
547792cccca0SStefano Zampini     opts = PETSC_FALSE;
5478304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
547992cccca0SStefano Zampini       opts = PETSC_TRUE;
5480304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5481304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5482304d26faSStefano Zampini       /* default */
5483304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5484e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
54852f37b69bSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->pA_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5486304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
54879577ea80SStefano Zampini       if (issbaij) {
54889577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
54899577ea80SStefano Zampini       } else {
5490304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
54919577ea80SStefano Zampini       }
5492399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure);CHKERRQ(ierr);
549392cccca0SStefano Zampini     }
549492cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(pcis->pA_II,((PetscObject)pcbddc->ksp_D)->prefix);CHKERRQ(ierr);
54952f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->pA_II);CHKERRQ(ierr);
5496304d26faSStefano Zampini     /* Allow user's customization */
549792cccca0SStefano Zampini     if (opts) {
5498304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
549992cccca0SStefano Zampini     }
55006d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pcis->pA_II,&nnsp);CHKERRQ(ierr);
55016d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */
55026d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II);CHKERRQ(ierr);
550392cccca0SStefano Zampini     }
550492cccca0SStefano Zampini     ierr = MatGetNearNullSpace(pcis->pA_II,&nnsp);CHKERRQ(ierr);
550592cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5506cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
550792cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5508cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5509cd18cfedSStefano Zampini       const PetscInt *idxs;
5510cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5511cd18cfedSStefano Zampini 
5512cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5513cd18cfedSStefano Zampini       ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5514cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5515cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5516cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5517cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5518cd18cfedSStefano Zampini         }
5519cd18cfedSStefano Zampini       }
5520cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5521cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5522cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5523cd18cfedSStefano Zampini     }
5524b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5525df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5526d62866d3SStefano Zampini 
5527df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5528d5574798SStefano Zampini     }
552992cccca0SStefano Zampini 
5530304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5531304d26faSStefano Zampini     if (!n_D) {
5532304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5533304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5534304d26faSStefano Zampini     }
553593120301SStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
5536304d26faSStefano Zampini     /* set ksp_D into pcis data */
5537304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
553892cccca0SStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5539304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5540684f6988SStefano Zampini   }
5541304d26faSStefano Zampini 
5542304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5543684f6988SStefano Zampini   A_RR = 0;
5544684f6988SStefano Zampini   if (neumann) {
5545d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
554604708bb6SStefano Zampini     PetscInt        ibs,mbs;
55470aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
554804708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
55490aa714b2SStefano Zampini 
55500aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
55510aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
55520aa714b2SStefano Zampini       IS iP;
55530aa714b2SStefano Zampini 
55540aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
55550aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
55560aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
55570aa714b2SStefano Zampini     }
5558f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
55598ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5560f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5561f4ddd8eeSStefano Zampini       PetscInt nn_R;
556281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5563f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5564f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5565f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5566f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5567f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5568f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5569f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5570727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5571f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5572f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5573f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5574f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5575f4ddd8eeSStefano Zampini         }
5576f4ddd8eeSStefano Zampini       }
5577f4ddd8eeSStefano Zampini       /* last check */
5578d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5579f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5580f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5581f4ddd8eeSStefano Zampini       }
5582f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5583f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5584f4ddd8eeSStefano Zampini     }
5585365a3a41SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection
5586365a3a41SStefano Zampini        TODO: Get Rid of these conversions */
5587af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5588af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
558904708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
559004708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
559104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
559204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
559304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5594af732b37SStefano Zampini       } else {
5595511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
55966816873aSStefano Zampini       }
559704708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
559804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
559904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5600365a3a41SStefano Zampini         ierr = MatConvert(matis->A,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
560104708bb6SStefano Zampini       } else {
5602365a3a41SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
560304708bb6SStefano Zampini       }
560404708bb6SStefano Zampini     }
5605a00504b5SStefano Zampini     /* extract A_RR */
56060aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5607a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5608a00504b5SStefano Zampini 
5609a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
561016e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5611a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
561216e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
561316e386b8SStefano Zampini         } else {
56147dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5615a00504b5SStefano Zampini         }
5616a00504b5SStefano Zampini       } else {
5617a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5618a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5619a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5620a00504b5SStefano Zampini       }
5621a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
56227dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
562316e386b8SStefano Zampini     }
56243301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5625d1e098c7SStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
56266816873aSStefano Zampini     }
562792cccca0SStefano Zampini     opts = PETSC_FALSE;
5628f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
562992cccca0SStefano Zampini       opts = PETSC_TRUE;
5630304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5631304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5632304d26faSStefano Zampini       /* default */
5633304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5634e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5635304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
56369577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
56379577ea80SStefano Zampini       if (issbaij) {
56389577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
56399577ea80SStefano Zampini       } else {
5640304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
56419577ea80SStefano Zampini       }
5642399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure);CHKERRQ(ierr);
564392cccca0SStefano Zampini     }
56442f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
564592cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix);CHKERRQ(ierr);
564692cccca0SStefano Zampini     if (opts) { /* Allow user's customization once */
5647304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
564892cccca0SStefano Zampini     }
56496d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(A_RR,&nnsp);CHKERRQ(ierr);
56506d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */
56516d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR);CHKERRQ(ierr);
565292cccca0SStefano Zampini     }
565392cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A_RR,&nnsp);CHKERRQ(ierr);
565492cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5655cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
565692cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5657cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5658cd18cfedSStefano Zampini       const PetscInt *idxs;
5659cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5660cd18cfedSStefano Zampini 
5661cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5662cd18cfedSStefano Zampini       ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5663cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5664cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5665cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5666cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5667cd18cfedSStefano Zampini         }
5668cd18cfedSStefano Zampini       }
5669cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5670cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5671cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5672cd18cfedSStefano Zampini     }
567392cccca0SStefano Zampini 
5674304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5675304d26faSStefano Zampini     if (!n_R) {
5676304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5677304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5678304d26faSStefano Zampini     }
5679df4d28bfSStefano Zampini     /* Reuse solver if it is present */
56800aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5681df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5682d62866d3SStefano Zampini 
5683df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5684d62866d3SStefano Zampini     }
568593120301SStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
5686684f6988SStefano Zampini   }
5687304d26faSStefano Zampini 
5688684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5689684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
56901575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5691684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5692684f6988SStefano Zampini   }
56938ead10e4SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5694c7017625SStefano Zampini 
5695c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
5696c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5697c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5698c7017625SStefano Zampini   }
5699c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
5700c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5701c7017625SStefano Zampini   }
5702c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
5703c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5704c7017625SStefano Zampini   }
5705c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5706c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5707684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
57080fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
57090fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
57100fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
5711c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
57120fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
57130fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5714e604994aSStefano 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);
5715304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5716304d26faSStefano Zampini     }
5717684f6988SStefano Zampini     if (neumann) { /* Neumann */
57180fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
57190fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
57200fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5721c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
57220fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
57230fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5724e604994aSStefano 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);
5725304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5726304d26faSStefano Zampini     }
5727684f6988SStefano Zampini   }
57285cbda25cSStefano Zampini   /* free Neumann problem's matrix */
57295cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5730304d26faSStefano Zampini   PetscFunctionReturn(0);
5731304d26faSStefano Zampini }
5732304d26faSStefano Zampini 
573380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5734674ae819SStefano Zampini {
5735674ae819SStefano Zampini   PetscErrorCode  ierr;
5736674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5737be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5738b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5739674ae819SStefano Zampini 
5740674ae819SStefano Zampini   PetscFunctionBegin;
5741b334f244SStefano Zampini   if (!reuse_solver) {
574280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
574320c7b377SStefano Zampini   }
574480677318SStefano Zampini   if (!pcbddc->switch_static) {
574580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
574680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
574780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
574820c7b377SStefano Zampini     }
5749b334f244SStefano Zampini     if (!reuse_solver) {
575080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
575180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
575220c7b377SStefano Zampini     } else {
5753df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5754be83ff47SStefano Zampini 
5755df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5756df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
575720c7b377SStefano Zampini     }
5758be83ff47SStefano Zampini   } else {
575980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
576080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
576180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
576280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
576380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
576480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
576580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
576680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
576780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5768674ae819SStefano Zampini     }
5769674ae819SStefano Zampini   }
5770b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
577180677318SStefano Zampini     if (applytranspose) {
577280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
577380677318SStefano Zampini     } else {
577480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
577580677318SStefano Zampini     }
5776c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R);CHKERRQ(ierr);
5777be83ff47SStefano Zampini   } else {
5778df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5779be83ff47SStefano Zampini 
5780be83ff47SStefano Zampini     if (applytranspose) {
5781df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5782be83ff47SStefano Zampini     } else {
5783df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5784be83ff47SStefano Zampini     }
5785be83ff47SStefano Zampini   }
578680677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
578780677318SStefano Zampini   if (!pcbddc->switch_static) {
5788b334f244SStefano Zampini     if (!reuse_solver) {
578980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
579080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5791be83ff47SStefano Zampini     } else {
5792df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5793be83ff47SStefano Zampini 
5794df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5795df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5796be83ff47SStefano Zampini     }
579780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
579880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
579980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
580080677318SStefano Zampini     }
580180677318SStefano Zampini   } else {
580280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
580380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
580480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
580580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
580680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
580780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
580880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
580980677318SStefano Zampini     }
581080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
581180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
581280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
581380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5814674ae819SStefano Zampini   }
5815674ae819SStefano Zampini   PetscFunctionReturn(0);
5816674ae819SStefano Zampini }
5817674ae819SStefano Zampini 
5818dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5819dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5820674ae819SStefano Zampini {
5821674ae819SStefano Zampini   PetscErrorCode ierr;
5822674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5823674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5824674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5825674ae819SStefano Zampini 
5826674ae819SStefano Zampini   PetscFunctionBegin;
5827dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
58284fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5829dc359a40SStefano Zampini     if (applytranspose) {
5830674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
58318eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5832dc359a40SStefano Zampini     } else {
5833674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5834674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
583515aaf578SStefano Zampini     }
58364fee134fSStefano Zampini   } else {
58374fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
58384fee134fSStefano Zampini   }
5839efc2fbd9SStefano Zampini 
5840efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
58414f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5842efc2fbd9SStefano Zampini     PetscScalar *array;
58434f1b2e48SStefano Zampini     PetscInt    j;
5844efc2fbd9SStefano Zampini 
5845efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
58464f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5847efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5848efc2fbd9SStefano Zampini   }
5849efc2fbd9SStefano Zampini 
585012edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
585112edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
585212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
585312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
585412edc857SStefano Zampini 
58559f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
585612edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
585751694757SStefano Zampini     Mat          coarse_mat;
5858964fefecSStefano Zampini     Vec          rhs,sol;
585951694757SStefano Zampini     MatNullSpace nullsp;
586027b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5861964fefecSStefano Zampini 
586227b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
586327b6a85dSStefano Zampini       PC        coarse_pc;
586427b6a85dSStefano Zampini 
586527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
586627b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
586727b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
586827b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
586927b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
587027b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
58713bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
587227b6a85dSStefano Zampini       }
587327b6a85dSStefano Zampini     }
5874964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5875964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
587651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
587712edc857SStefano Zampini     if (applytranspose) {
58789a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5879964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
5880c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
58819bfcb8eaSStefano Zampini       ierr = MatGetTransposeNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
58829bfcb8eaSStefano Zampini       if (nullsp) {
58839bfcb8eaSStefano Zampini         ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
58849bfcb8eaSStefano Zampini       }
58852701bc32SStefano Zampini     } else {
58869bfcb8eaSStefano Zampini       ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
58871f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
58882701bc32SStefano Zampini         PC        coarse_pc;
58892701bc32SStefano Zampini 
58909bfcb8eaSStefano Zampini         if (nullsp) {
58919bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
58929bfcb8eaSStefano Zampini         }
58932701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
58942701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
58953e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
58962701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
589712edc857SStefano Zampini       } else {
5898964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
5899c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
59009bfcb8eaSStefano Zampini         if (nullsp) {
59019bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
59029bfcb8eaSStefano Zampini         }
590312edc857SStefano Zampini       }
59042701bc32SStefano Zampini     }
59051d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
590627b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
590727b6a85dSStefano Zampini       PC        coarse_pc;
590827b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
590927b6a85dSStefano Zampini 
591027b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
591127b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
591227b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
59133bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
591427b6a85dSStefano Zampini     }
591512edc857SStefano Zampini   }
5916674ae819SStefano Zampini 
5917674ae819SStefano Zampini   /* Local solution on R nodes */
59184fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
591980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
59209f00e9b4SStefano Zampini   }
59219f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
59229f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
592312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5924674ae819SStefano Zampini 
59254fee134fSStefano Zampini   /* Sum contributions from the two levels */
59264fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5927dc359a40SStefano Zampini     if (applytranspose) {
5928dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5929dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5930dc359a40SStefano Zampini     } else {
5931674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
59328eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5933dc359a40SStefano Zampini     }
5934efc2fbd9SStefano Zampini     /* store p0 */
59354f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5936efc2fbd9SStefano Zampini       PetscScalar *array;
59374f1b2e48SStefano Zampini       PetscInt    j;
5938efc2fbd9SStefano Zampini 
5939efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
59404f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5941efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5942efc2fbd9SStefano Zampini     }
59434fee134fSStefano Zampini   } else { /* expand the coarse solution */
59444fee134fSStefano Zampini     if (applytranspose) {
59454fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
59464fee134fSStefano Zampini     } else {
59474fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
59484fee134fSStefano Zampini     }
59494fee134fSStefano Zampini   }
5950674ae819SStefano Zampini   PetscFunctionReturn(0);
5951674ae819SStefano Zampini }
5952674ae819SStefano Zampini 
595312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5954674ae819SStefano Zampini {
5955674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
595612edc857SStefano Zampini   Vec               from,to;
59577ebab0bbSStefano Zampini   const PetscScalar *array;
59587ebab0bbSStefano Zampini   PetscErrorCode    ierr;
5959674ae819SStefano Zampini 
5960674ae819SStefano Zampini   PetscFunctionBegin;
596112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
596212edc857SStefano Zampini     from = pcbddc->coarse_vec;
596312edc857SStefano Zampini     to = pcbddc->vec1_P;
596412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
596512edc857SStefano Zampini       Vec tvec;
596658da7f69SStefano Zampini 
596758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
596858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
596912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
59707ebab0bbSStefano Zampini       ierr = VecGetArrayRead(tvec,&array);CHKERRQ(ierr);
597158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
59727ebab0bbSStefano Zampini       ierr = VecRestoreArrayRead(tvec,&array);CHKERRQ(ierr);
597312edc857SStefano Zampini     }
597412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
597512edc857SStefano Zampini     from = pcbddc->vec1_P;
597612edc857SStefano Zampini     to = pcbddc->coarse_vec;
597712edc857SStefano Zampini   }
597812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5979674ae819SStefano Zampini   PetscFunctionReturn(0);
5980674ae819SStefano Zampini }
5981674ae819SStefano Zampini 
598212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5983674ae819SStefano Zampini {
5984674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
598512edc857SStefano Zampini   Vec               from,to;
59867ebab0bbSStefano Zampini   const PetscScalar *array;
59877ebab0bbSStefano Zampini   PetscErrorCode    ierr;
5988674ae819SStefano Zampini 
5989674ae819SStefano Zampini   PetscFunctionBegin;
599012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
599112edc857SStefano Zampini     from = pcbddc->coarse_vec;
599212edc857SStefano Zampini     to = pcbddc->vec1_P;
599312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
599412edc857SStefano Zampini     from = pcbddc->vec1_P;
599512edc857SStefano Zampini     to = pcbddc->coarse_vec;
599612edc857SStefano Zampini   }
599712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
599812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
599912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
600012edc857SStefano Zampini       Vec tvec;
600158da7f69SStefano Zampini 
600212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
60037ebab0bbSStefano Zampini       ierr = VecGetArrayRead(to,&array);CHKERRQ(ierr);
600458da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
60057ebab0bbSStefano Zampini       ierr = VecRestoreArrayRead(to,&array);CHKERRQ(ierr);
600658da7f69SStefano Zampini     }
600758da7f69SStefano Zampini   } else {
600858da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
600958da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
601012edc857SStefano Zampini     }
601112edc857SStefano Zampini   }
6012674ae819SStefano Zampini   PetscFunctionReturn(0);
6013674ae819SStefano Zampini }
6014674ae819SStefano Zampini 
6015674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
6016674ae819SStefano Zampini {
6017674ae819SStefano Zampini   PetscErrorCode    ierr;
6018674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
6019674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6020674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
6021984c4197SStefano Zampini   /* one and zero */
6022984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
6023984c4197SStefano Zampini   /* space to store constraints and their local indices */
60249162d606SStefano Zampini   PetscScalar       *constraints_data;
60259162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
60269162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
60279162d606SStefano Zampini   PetscInt          *constraints_n;
6028984c4197SStefano Zampini   /* iterators */
6029b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
6030984c4197SStefano Zampini   /* BLAS integers */
6031e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
6032e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
6033c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
6034727cdba6SStefano Zampini   /* reuse */
60350e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
60360e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
6037984c4197SStefano Zampini   /* change of basis */
6038b3d85658SStefano Zampini   PetscBool         qr_needed;
60399162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
6040984c4197SStefano Zampini   /* auxiliary stuff */
604164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
60428a0068c3SStefano Zampini   PetscInt          ncc;
6043984c4197SStefano Zampini   /* some quantities */
604445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
6045a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
604657715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
6047984c4197SStefano Zampini 
6048674ae819SStefano Zampini   PetscFunctionBegin;
604957715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
60508e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
60518e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
60528e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
605316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
6054088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
6055088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
60560e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
60570e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
6058580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc);CHKERRQ(ierr);
6059580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc);CHKERRQ(ierr);
60600e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
6061088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
6062cf5a6209SStefano Zampini 
6063cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
60649162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
6065cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
6066cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
6067cf5a6209SStefano Zampini     Vec          *localnearnullsp;
6068cf5a6209SStefano Zampini     PetscScalar  *array;
6069cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
6070cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
6071674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
6072b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
6073674ae819SStefano Zampini     PetscScalar  *work;
6074674ae819SStefano Zampini     PetscReal    *singular_vals;
6075674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6076674ae819SStefano Zampini     PetscReal    *rwork;
6077674ae819SStefano Zampini #endif
607855080a34SStefano Zampini     PetscScalar  *temp_basis = NULL,*correlation_mat = NULL;
6079964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
6080964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
608155080a34SStefano Zampini     PetscBool    use_pod = PETSC_FALSE;
6082674ae819SStefano Zampini 
608355080a34SStefano Zampini     /* MKL SVD with same input gives different results on different processes! */
608455080a34SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL)
608555080a34SStefano Zampini     use_pod = PETSC_TRUE;
608655080a34SStefano Zampini #endif
6087674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
6088d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
6089e4d548c7SStefano Zampini     /* print some info */
60905c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
6091e4d548c7SStefano Zampini       PetscInt nv;
6092e4d548c7SStefano Zampini 
6093c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6094e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
6095e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6096e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
60976080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
60986080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
60996080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
6100e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6101e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6102e4d548c7SStefano Zampini     }
6103e4d548c7SStefano Zampini 
6104d06fc5fdSStefano Zampini     /* free unneeded index sets */
6105d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
6106d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
6107674ae819SStefano Zampini     }
6108d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
6109d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
6110d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6111d06fc5fdSStefano Zampini       }
6112d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6113d06fc5fdSStefano Zampini       n_ISForEdges = 0;
6114d06fc5fdSStefano Zampini     }
6115d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
6116d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
6117d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6118d06fc5fdSStefano Zampini       }
6119d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6120d06fc5fdSStefano Zampini       n_ISForFaces = 0;
6121d06fc5fdSStefano Zampini     }
612270022509SStefano Zampini 
6123674ae819SStefano Zampini     /* check if near null space is attached to global mat */
61246d9e27e4SStefano Zampini     if (pcbddc->use_nnsp) {
6125674ae819SStefano Zampini       ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
61266d9e27e4SStefano Zampini     } else nearnullsp = NULL;
61276d9e27e4SStefano Zampini 
6128674ae819SStefano Zampini     if (nearnullsp) {
6129674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
6130f4ddd8eeSStefano Zampini       /* remove any stored info */
6131f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
6132f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6133f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
6134f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
6135f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
6136473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6137f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
6138f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
6139f4ddd8eeSStefano Zampini       }
6140984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
6141984c4197SStefano Zampini       nnsp_size = 0;
6142674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
6143674ae819SStefano Zampini     }
6144984c4197SStefano Zampini     /* get max number of constraints on a single cc */
6145984c4197SStefano Zampini     max_constraints = nnsp_size;
6146984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
6147984c4197SStefano Zampini 
6148674ae819SStefano Zampini     /*
6149674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
61509162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
61519162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
61529162d606SStefano Zampini          There can be multiple constraints per connected component
6153674ae819SStefano Zampini                                                                                                                                                            */
6154674ae819SStefano Zampini     n_vertices = 0;
6155674ae819SStefano Zampini     if (ISForVertices) {
6156674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
6157674ae819SStefano Zampini     }
61589162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
61599162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
61609162d606SStefano Zampini 
61619162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
61629162d606SStefano Zampini     total_counts *= max_constraints;
6163674ae819SStefano Zampini     total_counts += n_vertices;
61644641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
61659162d606SStefano Zampini 
6166674ae819SStefano Zampini     total_counts = 0;
6167674ae819SStefano Zampini     max_size_of_constraint = 0;
6168674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
61699162d606SStefano Zampini       IS used_is;
6170674ae819SStefano Zampini       if (i<n_ISForEdges) {
61719162d606SStefano Zampini         used_is = ISForEdges[i];
6172674ae819SStefano Zampini       } else {
61739162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
6174674ae819SStefano Zampini       }
61759162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
6176674ae819SStefano Zampini       total_counts += j;
6177674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
6178674ae819SStefano Zampini     }
61799162d606SStefano 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);
61809162d606SStefano Zampini 
6181984c4197SStefano Zampini     /* get local part of global near null space vectors */
6182785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
6183984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6184984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
6185e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6186e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6187984c4197SStefano Zampini     }
6188674ae819SStefano Zampini 
6189242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
6190242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
6191a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
6192242a89d7SStefano Zampini 
6193984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
6194a773dcb8SStefano Zampini     if (!skip_lapack) {
6195674ae819SStefano Zampini       PetscScalar temp_work;
6196911cabfeSStefano Zampini 
619755080a34SStefano Zampini       if (use_pod) {
6198984c4197SStefano Zampini         /* Proper Orthogonal Decomposition (POD) using the snapshot method */
6199785e854fSJed Brown         ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
6200785e854fSJed Brown         ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
6201785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
6202674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6203785e854fSJed Brown         ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
6204674ae819SStefano Zampini #endif
6205674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6206c8244a33SStefano Zampini         ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
6207c8244a33SStefano Zampini         ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
6208674ae819SStefano Zampini         lwork = -1;
6209674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6210674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6211c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6212674ae819SStefano Zampini #else
6213c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6214674ae819SStefano Zampini #endif
6215674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
6216984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
621755080a34SStefano Zampini       } else {
621855080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6219674ae819SStefano Zampini         /* SVD */
6220674ae819SStefano Zampini         PetscInt max_n,min_n;
6221674ae819SStefano Zampini         max_n = max_size_of_constraint;
6222984c4197SStefano Zampini         min_n = max_constraints;
6223984c4197SStefano Zampini         if (max_size_of_constraint < max_constraints) {
6224674ae819SStefano Zampini           min_n = max_size_of_constraint;
6225984c4197SStefano Zampini           max_n = max_constraints;
6226674ae819SStefano Zampini         }
6227785e854fSJed Brown         ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
6228674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6229785e854fSJed Brown         ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
6230674ae819SStefano Zampini #endif
6231674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6232674ae819SStefano Zampini         lwork = -1;
6233e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
6234e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
6235b7d8b9f8SStefano Zampini         ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
6236674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6237674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
62389162d606SStefano 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));
6239674ae819SStefano Zampini #else
62409162d606SStefano 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));
6241674ae819SStefano Zampini #endif
6242674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
6243984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
624455080a34SStefano Zampini #else
624555080a34SStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6246984c4197SStefano Zampini #endif /* on missing GESVD */
624755080a34SStefano Zampini       }
6248674ae819SStefano Zampini       /* Allocate optimal workspace */
6249674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
6250854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
6251674ae819SStefano Zampini     }
6252674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6253674ae819SStefano Zampini     total_counts = 0;
62549162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
62559162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6256674ae819SStefano Zampini     /* vertices */
62579162d606SStefano Zampini     if (n_vertices) {
6258674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6259580bdb30SBarry Smith       ierr = PetscArraycpy(constraints_idxs,is_indices,n_vertices);CHKERRQ(ierr);
6260674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
62619162d606SStefano Zampini         constraints_n[total_counts] = 1;
62629162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
62639162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
62649162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6265674ae819SStefano Zampini         total_counts++;
6266674ae819SStefano Zampini       }
6267674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6268674ae819SStefano Zampini       n_vertices = total_counts;
6269674ae819SStefano Zampini     }
6270984c4197SStefano Zampini 
6271674ae819SStefano Zampini     /* edges and faces */
62729162d606SStefano Zampini     total_counts_cc = total_counts;
6273911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
62749162d606SStefano Zampini       IS        used_is;
62759162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
62769162d606SStefano Zampini 
6277911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
62789162d606SStefano Zampini         used_is = ISForEdges[ncc];
6279984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6280674ae819SStefano Zampini       } else {
62819162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6282984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6283674ae819SStefano Zampini       }
6284674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
62859162d606SStefano Zampini 
62869162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
62879162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6288984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6289984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6290674ae819SStefano Zampini       if (nnsp_has_cnst) {
62915b08dc53SStefano Zampini         PetscScalar quad_value;
62929162d606SStefano Zampini 
6293580bdb30SBarry Smith         ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
62949162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
62959162d606SStefano Zampini 
6296a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6297674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6298a773dcb8SStefano Zampini         } else {
6299a773dcb8SStefano Zampini           quad_value = 1.0;
6300a773dcb8SStefano Zampini         }
6301674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63029162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6303674ae819SStefano Zampini         }
63049162d606SStefano Zampini         temp_constraints++;
6305674ae819SStefano Zampini         total_counts++;
6306674ae819SStefano Zampini       }
6307674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6308984c4197SStefano Zampini         PetscReal real_value;
63099162d606SStefano Zampini         PetscScalar *ptr_to_data;
63109162d606SStefano Zampini 
6311984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
63129162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6313674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63149162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6315674ae819SStefano Zampini         }
6316984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
6317984c4197SStefano Zampini         /* check if array is null on the connected component */
6318e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63199162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
632057715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6321674ae819SStefano Zampini           temp_constraints++;
6322674ae819SStefano Zampini           total_counts++;
63239162d606SStefano Zampini           if (!idxs_copied) {
6324580bdb30SBarry Smith             ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
63259162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6326674ae819SStefano Zampini           }
6327674ae819SStefano Zampini         }
63289162d606SStefano Zampini       }
63299162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
633045a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6331eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6332a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
63339162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
63349162d606SStefano Zampini 
63359162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6336a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63379162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6338a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
63399162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6340a773dcb8SStefano Zampini         } else { /* perform SVD */
63419162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6342674ae819SStefano Zampini 
634355080a34SStefano Zampini           if (use_pod) {
6344984c4197SStefano Zampini             /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6345984c4197SStefano Zampini                POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6346984c4197SStefano Zampini                -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6347984c4197SStefano Zampini                   the constraints basis will differ (by a complex factor with absolute value equal to 1)
6348984c4197SStefano Zampini                   from that computed using LAPACKgesvd
6349984c4197SStefano Zampini                -> This is due to a different computation of eigenvectors in LAPACKheev
6350984c4197SStefano Zampini                -> The quality of the POD-computed basis will be the same */
6351580bdb30SBarry Smith             ierr = PetscArrayzero(correlation_mat,temp_constraints*temp_constraints);CHKERRQ(ierr);
6352674ae819SStefano Zampini             /* Store upper triangular part of correlation matrix */
6353e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6354984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6355674ae819SStefano Zampini             for (j=0;j<temp_constraints;j++) {
6356674ae819SStefano Zampini               for (k=0;k<j+1;k++) {
63579162d606SStefano 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));
6358674ae819SStefano Zampini               }
6359674ae819SStefano Zampini             }
6360e310c8b4SStefano Zampini             /* compute eigenvalues and eigenvectors of correlation matrix */
6361e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6362e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6363674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6364c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6365674ae819SStefano Zampini #else
6366c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6367674ae819SStefano Zampini #endif
6368674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6369984c4197SStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6370984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6371674ae819SStefano Zampini             j = 0;
637287b3baaaSStefano Zampini             while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6373674ae819SStefano Zampini             total_counts = total_counts-j;
637445a1bb75SStefano Zampini             valid_constraints = temp_constraints-j;
6375e310c8b4SStefano Zampini             /* scale and copy POD basis into used quadrature memory */
6376c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6377c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6378c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6379c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6380c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6381c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6382674ae819SStefano Zampini             if (j<temp_constraints) {
6383984c4197SStefano Zampini               PetscInt ii;
6384984c4197SStefano Zampini               for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6385674ae819SStefano Zampini               ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63869162d606SStefano 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));
6387674ae819SStefano Zampini               ierr = PetscFPTrapPop();CHKERRQ(ierr);
6388984c4197SStefano Zampini               for (k=0;k<temp_constraints-j;k++) {
6389674ae819SStefano Zampini                 for (ii=0;ii<size_of_constraint;ii++) {
63909162d606SStefano 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];
6391674ae819SStefano Zampini                 }
6392674ae819SStefano Zampini               }
6393674ae819SStefano Zampini             }
639455080a34SStefano Zampini           } else {
639555080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6396e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6397e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6398b7d8b9f8SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6399674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6400674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
64019162d606SStefano 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));
6402674ae819SStefano Zampini #else
64039162d606SStefano 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));
6404674ae819SStefano Zampini #endif
6405984c4197SStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6406674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6407984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6408e310c8b4SStefano Zampini             k = temp_constraints;
6409e310c8b4SStefano Zampini             if (k > size_of_constraint) k = size_of_constraint;
6410674ae819SStefano Zampini             j = 0;
641187b3baaaSStefano Zampini             while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
641245a1bb75SStefano Zampini             valid_constraints = k-j;
6413911cabfeSStefano Zampini             total_counts = total_counts-temp_constraints+valid_constraints;
641455080a34SStefano Zampini #else
641555080a34SStefano Zampini             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6416984c4197SStefano Zampini #endif /* on missing GESVD */
6417674ae819SStefano Zampini           }
6418a773dcb8SStefano Zampini         }
641955080a34SStefano Zampini       }
64209162d606SStefano Zampini       /* update pointers information */
64219162d606SStefano Zampini       if (valid_constraints) {
64229162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
64239162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
64249162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
64259162d606SStefano Zampini         /* set change_of_basis flag */
642645a1bb75SStefano Zampini         if (boolforchange) {
6427b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
64289162d606SStefano Zampini         }
6429b3d85658SStefano Zampini         total_counts_cc++;
643045a1bb75SStefano Zampini       }
643145a1bb75SStefano Zampini     }
6432984c4197SStefano Zampini     /* free workspace */
64338f1c130eSStefano Zampini     if (!skip_lapack) {
6434984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6435984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6436984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6437984c4197SStefano Zampini #endif
6438984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6439984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6440984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6441984c4197SStefano Zampini     }
6442984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6443984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6444984c4197SStefano Zampini     }
6445984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6446cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6447cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6448cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6449cf5a6209SStefano Zampini     }
6450cf5a6209SStefano Zampini     if (n_ISForFaces) {
6451cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6452cf5a6209SStefano Zampini     }
6453cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6454cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6455cf5a6209SStefano Zampini     }
6456cf5a6209SStefano Zampini     if (n_ISForEdges) {
6457cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6458cf5a6209SStefano Zampini     }
6459cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
646008122e43SStefano Zampini   } else {
646108122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6462984c4197SStefano Zampini 
646308122e43SStefano Zampini     total_counts = 0;
646408122e43SStefano Zampini     n_vertices = 0;
6465d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6466d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
646708122e43SStefano Zampini     }
646808122e43SStefano Zampini     max_constraints = 0;
64699162d606SStefano Zampini     total_counts_cc = 0;
647008122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
647108122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
64729162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
647308122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
647408122e43SStefano Zampini     }
64759162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
64769162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
64779162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
64789162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
647974d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
64809162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
64819162d606SStefano Zampini     total_counts_cc = 0;
64829162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
64839162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
64849162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
648508122e43SStefano Zampini       }
648608122e43SStefano Zampini     }
648708122e43SStefano Zampini 
64888bec7fa6SStefano Zampini     max_size_of_constraint = 0;
64899162d606SStefano 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]);
64909162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
649108122e43SStefano Zampini     /* Change of basis */
6492b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
649308122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
649408122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
649508122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6496b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
649708122e43SStefano Zampini         }
649808122e43SStefano Zampini       }
649908122e43SStefano Zampini     }
650008122e43SStefano Zampini   }
6501984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
65024f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
650308122e43SStefano Zampini 
65049162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
65059162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
65066080607fSStefano 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",constraints_idxs_ptr[total_counts_cc],i);
6507674ae819SStefano Zampini 
6508674ae819SStefano Zampini   /* Create constraint matrix */
6509674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
651016f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6511984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6512984c4197SStefano Zampini 
6513984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6514a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
65155a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
651674d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6517984c4197SStefano Zampini   total_primal_vertices=0;
6518b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
65199162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
65209162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
652172b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
65229162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6523b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
652464efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
65259162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65269162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6527a717540cSStefano Zampini       }
6528b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
652991af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6530a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6531a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6532a717540cSStefano Zampini       }
6533fa434743SStefano Zampini     } else {
6534b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6535fa434743SStefano Zampini     }
6536a717540cSStefano Zampini   }
6537b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6538b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6539674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
654070022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
65414f1b2e48SStefano 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);
6542580bdb30SBarry Smith   ierr = PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices);CHKERRQ(ierr);
65430e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6544984c4197SStefano Zampini 
6545984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
654674d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6547785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6548984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
654974d5cdf7SStefano Zampini 
6550984c4197SStefano Zampini   j = total_primal_vertices;
655174d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6552b3d85658SStefano Zampini   cum = total_primal_vertices;
65539162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65544641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6555b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6556b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6557b3d85658SStefano Zampini       cum++;
65589162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
655974d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
656074d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
656174d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
656274d5cdf7SStefano Zampini       }
65639162d606SStefano Zampini       j += constraints_n[i];
6564674ae819SStefano Zampini     }
6565674ae819SStefano Zampini   }
6566674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6567e1b21442SStefano Zampini   ierr = MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6568674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6569088faed8SStefano Zampini 
6570674ae819SStefano Zampini   /* set values in constraint matrix */
6571984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
65720e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6573674ae819SStefano Zampini   }
6574984c4197SStefano Zampini   total_counts = total_primal_vertices;
65759162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65764641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
65779162d606SStefano Zampini       PetscInt *cols;
65789162d606SStefano Zampini 
65799162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
65809162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
65819162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65829162d606SStefano Zampini         PetscInt    row = total_counts+k;
65839162d606SStefano Zampini         PetscScalar *vals;
65849162d606SStefano Zampini 
65859162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
65869162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
65879162d606SStefano Zampini       }
65889162d606SStefano Zampini       total_counts += constraints_n[i];
6589674ae819SStefano Zampini     }
6590674ae819SStefano Zampini   }
6591674ae819SStefano Zampini   /* assembling */
6592674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6593674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65947ebab0bbSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,(PetscObject)pc,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6595088faed8SStefano Zampini 
6596674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6597674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6598026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6599984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6600984c4197SStefano Zampini     /* working stuff for GEQRF */
66015a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6602984c4197SStefano Zampini     PetscBLASInt lqr_work;
6603984c4197SStefano Zampini     /* working stuff for UNGQR */
66045a52fde0SStefano Zampini     PetscScalar  *gqr_work = NULL,lgqr_work_t;
6605984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6606984c4197SStefano Zampini     /* working stuff for TRTRS */
66075a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
66083f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6609984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6610984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6611984c4197SStefano Zampini     PetscScalar  *start_vals;
6612984c4197SStefano Zampini     /* working stuff for values insertion */
66134641a718SStefano Zampini     PetscBT      is_primal;
661464efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6615906d46d4SStefano Zampini     /* matrix sizes */
6616906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6617906d46d4SStefano Zampini     /* temporary change of basis */
6618906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6619cf5a6209SStefano Zampini     /* extra space for debugging */
66205a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6621984c4197SStefano Zampini 
6622906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6623906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
662416f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6625bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6626906d46d4SStefano Zampini     /* nonzeros for local mat */
6627bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
66281dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6629bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
66301dd7afcfSStefano Zampini     } else {
66311dd7afcfSStefano Zampini       const PetscInt *ii;
66321dd7afcfSStefano Zampini       PetscInt       n;
66331dd7afcfSStefano Zampini       PetscBool      flg_row;
66341dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
66351dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
66361dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
66371dd7afcfSStefano Zampini     }
66389162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6639a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
66409162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6641a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
66429162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6643a717540cSStefano Zampini         } else {
66449162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
66459162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6646a717540cSStefano Zampini         }
6647a717540cSStefano Zampini       }
6648a717540cSStefano Zampini     }
6649906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6650e1b21442SStefano Zampini     ierr = MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6651bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
66521dd7afcfSStefano Zampini     /* Set interior change in the matrix */
66531dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6654bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6655906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6656a717540cSStefano Zampini       }
66571dd7afcfSStefano Zampini     } else {
66581dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
66591dd7afcfSStefano Zampini       PetscScalar    *aa;
66601dd7afcfSStefano Zampini       PetscInt       n;
66611dd7afcfSStefano Zampini       PetscBool      flg_row;
66621dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
66631dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
66641dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
66651dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
66661dd7afcfSStefano Zampini       }
66671dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
66681dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
66691dd7afcfSStefano Zampini     }
6670a717540cSStefano Zampini 
6671a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6672a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6673a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6674a717540cSStefano Zampini     }
6675a717540cSStefano Zampini 
6676a717540cSStefano Zampini 
6677a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6678a717540cSStefano Zampini     /*
6679a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6680a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6681a717540cSStefano Zampini 
6682a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6683a717540cSStefano Zampini 
6684a6b551f4SStefano 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)
6685a6b551f4SStefano Zampini 
6686a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6687a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6688a717540cSStefano Zampini             |              ...                        |
6689a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6690a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6691a717540cSStefano Zampini 
6692a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6693a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6694a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6695a6b551f4SStefano Zampini 
6696a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6697a717540cSStefano Zampini     */
66985a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6699984c4197SStefano Zampini       /* space to store Q */
6700854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
67014e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
67024e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6703984c4197SStefano Zampini       /* first we issue queries for optimal work */
67043f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
67053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
67063f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6707984c4197SStefano Zampini       lqr_work = -1;
67083f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6709984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6710984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6711785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6712984c4197SStefano Zampini       lgqr_work = -1;
67133f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
67143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
67153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
67163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
67173f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6718c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6719c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6720984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6721785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6722984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6723785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6724a717540cSStefano Zampini       /* allocating workspace for check */
6725a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6726cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6727a717540cSStefano Zampini       }
6728a717540cSStefano Zampini     }
6729984c4197SStefano Zampini     /* array to store whether a node is primal or not */
67304641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6731473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
67320e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
67336080607fSStefano Zampini     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",total_primal_vertices,i);
673439e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
673539e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
673639e2fb2aSStefano Zampini     }
673739e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6738984c4197SStefano Zampini 
6739a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
67409162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
67419162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
67424641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6743984c4197SStefano Zampini         /* get constraint info */
67449162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6745984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6746984c4197SStefano Zampini 
6747984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
67486080607fSStefano 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);
6749674ae819SStefano Zampini         }
6750984c4197SStefano Zampini 
6751fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6752a717540cSStefano Zampini 
6753a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6754a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
6755580bdb30SBarry Smith             ierr = PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6756a717540cSStefano Zampini           }
6757984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
6758580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6759984c4197SStefano Zampini 
6760984c4197SStefano Zampini           /* compute QR decomposition of constraints */
67613f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67623f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
67633f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6764674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
67653f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6766984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6767674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6768984c4197SStefano Zampini 
6769984c4197SStefano Zampini           /* explictly compute R^-T */
6770580bdb30SBarry Smith           ierr = PetscArrayzero(trs_rhs,primal_dofs*primal_dofs);CHKERRQ(ierr);
6771984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
67723f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
67733f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
67743f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
67753f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6776984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
67773f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6778984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6779984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6780984c4197SStefano Zampini 
6781a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
67823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67833f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
67843f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
67853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6786984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6787c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6788c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6789984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6790984c4197SStefano Zampini 
6791984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6792984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6793984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
67943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
67963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
67973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
67983f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
67993f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6800984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
68019162d606SStefano 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));
6802984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6803580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6804984c4197SStefano Zampini 
6805984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
68069162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6807984c4197SStefano Zampini           /* insert cols for primal dofs */
6808984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6809984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
68109162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6811906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6812984c4197SStefano Zampini           }
6813984c4197SStefano Zampini           /* insert cols for dual dofs */
6814984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
68159162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6816984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
68179162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6818906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6819984c4197SStefano Zampini               j++;
6820674ae819SStefano Zampini             }
6821674ae819SStefano Zampini           }
6822984c4197SStefano Zampini 
6823984c4197SStefano Zampini           /* check change of basis */
6824984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6825984c4197SStefano Zampini             PetscInt   ii,jj;
6826984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6827c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6828c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6829c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6830c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6831c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6832c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6833984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6834cf5a6209SStefano 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));
6835984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6836984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6837984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6838cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6839c068d9bbSLisandro 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;
6840674ae819SStefano Zampini               }
6841674ae819SStefano Zampini             }
6842984c4197SStefano Zampini             if (!valid_qr) {
684322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6844984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6845984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6846cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
68476080607fSStefano Zampini                     ierr = 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]));CHKERRQ(ierr);
6848674ae819SStefano Zampini                   }
6849c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
68506080607fSStefano Zampini                     ierr = 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]));CHKERRQ(ierr);
6851984c4197SStefano Zampini                   }
6852984c4197SStefano Zampini                 }
6853984c4197SStefano Zampini               }
6854674ae819SStefano Zampini             } else {
685522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6856674ae819SStefano Zampini             }
6857674ae819SStefano Zampini           }
6858a717540cSStefano Zampini         } else { /* simple transformation block */
6859a717540cSStefano Zampini           PetscInt    row,col;
6860a6b551f4SStefano Zampini           PetscScalar val,norm;
6861a6b551f4SStefano Zampini 
6862a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
68639162d606SStefano 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));
6864a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
68659162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
68669162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6867bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
68689162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6869906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
68709162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6871a717540cSStefano Zampini             } else {
6872a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
68739162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6874a717540cSStefano Zampini                 if (row != col) {
68759162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6876a717540cSStefano Zampini                 } else {
68779162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6878a717540cSStefano Zampini                 }
6879906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6880a717540cSStefano Zampini               }
6881a717540cSStefano Zampini             }
6882a717540cSStefano Zampini           }
688398a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
688422d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6885a717540cSStefano Zampini           }
6886674ae819SStefano Zampini         }
6887984c4197SStefano Zampini       } else {
6888984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
68896080607fSStefano 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);
6890674ae819SStefano Zampini         }
6891674ae819SStefano Zampini       }
6892674ae819SStefano Zampini     }
6893a717540cSStefano Zampini 
6894a717540cSStefano Zampini     /* free workspace */
6895a717540cSStefano Zampini     if (qr_needed) {
6896984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6897cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6898984c4197SStefano Zampini       }
6899984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6900984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6901984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6902984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6903984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6904674ae819SStefano Zampini     }
6905a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6906906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6907906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6908906d46d4SStefano Zampini 
6909906d46d4SStefano Zampini     /* assembling of global change of variable */
691088c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6911bbb9e6c6SStefano Zampini       Mat      tmat;
691216f15bc4SStefano Zampini       PetscInt bs;
691316f15bc4SStefano Zampini 
6914906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6915906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6916bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6917bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6918487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6919487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6920bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6921bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
692216f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
692316f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6924906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6925bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6926487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6927bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6928bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6929bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6930e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6931e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6932bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6933bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
693488c03ad3SStefano Zampini 
6935906d46d4SStefano Zampini       /* check */
6936906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6937906d46d4SStefano Zampini         PetscReal error;
6938906d46d4SStefano Zampini         Vec       x,x_change;
6939906d46d4SStefano Zampini 
6940906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6941906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6942906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6943906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6944e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6945e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6946bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6947e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6948e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6949906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6950906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6951906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6952637e8532SStefano Zampini         if (error > PETSC_SMALL) {
69536080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
6954637e8532SStefano Zampini         }
6955906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6956906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6957906d46d4SStefano Zampini       }
6958b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6959b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6960b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6961bf3a8328SStefano Zampini 
696213903a91SSatish 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");
6963b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6964ac632422SStefano Zampini           Mat                    S_new,tmat;
6965bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6966bbb9e6c6SStefano Zampini 
6967bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
69687dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6969bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6970bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6971bf3a8328SStefano Zampini             IS                     is_V;
6972b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6973b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6974b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6975b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6976b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6977bf3a8328SStefano Zampini           }
6978bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6979ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6980b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6981ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6982bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6983bf3a8328SStefano Zampini             const PetscScalar *array;
6984bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6985bf3a8328SStefano Zampini             PetscInt          i,n_V;
6986bf3a8328SStefano Zampini 
6987b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6988b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6989b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6990b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6991b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6992b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6993b087196eSStefano Zampini               PetscScalar val;
6994b087196eSStefano Zampini               PetscInt    idx;
6995b087196eSStefano Zampini 
6996b087196eSStefano Zampini               idx = idxs_V[i];
6997b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6998b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6999b087196eSStefano Zampini             }
7000b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7001b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7002bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
7003bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
7004bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
7005bf3a8328SStefano Zampini           }
7006ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
7007ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
7008ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
7009ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
7010b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
7011ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
7012bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
7013b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
7014bf3a8328SStefano Zampini             }
7015ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
7016ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
7017ac632422SStefano Zampini           }
7018b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
701988c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
7020b96c3477SStefano Zampini         }
7021c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
7022b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
7023c9db6a07SStefano Zampini           PetscInt i;
7024c9db6a07SStefano Zampini 
7025c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
7026c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
7027c9db6a07SStefano Zampini           }
7028c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
7029c9db6a07SStefano Zampini         }
7030b96c3477SStefano Zampini       }
703116909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
703216909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
703316909a7fSStefano Zampini       } else {
7034906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
703516909a7fSStefano Zampini       }
70361dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
703727b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
703872b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
703972b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
704072b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
704172b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
704272b8c272SStefano Zampini     }
70431dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
704427b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
7045b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
7046b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
7047906d46d4SStefano Zampini     } else {
70481dd7afcfSStefano Zampini       Mat benign_global = NULL;
704927b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
70501dd7afcfSStefano Zampini         Mat M;
70511dd7afcfSStefano Zampini 
70529e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
70539e9b7b1fSStefano Zampini         ierr = VecCopy(matis->counter,pcis->vec1_N);CHKERRQ(ierr);
70549e9b7b1fSStefano Zampini         ierr = VecReciprocal(pcis->vec1_N);CHKERRQ(ierr);
70559e9b7b1fSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global);CHKERRQ(ierr);
70569e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
70571dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
70581dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
7059906d46d4SStefano Zampini         } else {
70609e9b7b1fSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M);CHKERRQ(ierr);
70619e9b7b1fSStefano Zampini           ierr = MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES);CHKERRQ(ierr);
7062906d46d4SStefano Zampini         }
70639e9b7b1fSStefano Zampini         ierr = MatISSetLocalMat(benign_global,M);CHKERRQ(ierr);
70649e9b7b1fSStefano Zampini         ierr = MatDestroy(&M);CHKERRQ(ierr);
70659e9b7b1fSStefano Zampini         ierr = MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70669e9b7b1fSStefano Zampini         ierr = MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70671dd7afcfSStefano Zampini       }
70681dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
70691dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
70701dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
707127b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
70721dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
70731dd7afcfSStefano Zampini       }
70741dd7afcfSStefano Zampini     }
707516909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
707616909a7fSStefano Zampini       IS             is_global;
707716909a7fSStefano Zampini       const PetscInt *gidxs;
707816909a7fSStefano Zampini 
707916909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
708016909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
708116909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
70827dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
708316909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
708416909a7fSStefano Zampini     }
70851dd7afcfSStefano Zampini   }
70861dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
70871dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
7088b9b85e73SStefano Zampini   }
7089a717540cSStefano Zampini 
709072b8c272SStefano Zampini   if (!pcbddc->fake_change) {
70914f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
70924f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
70934f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
70944f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
7095019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
7096019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
7097019a44ceSStefano Zampini       pcbddc->local_primal_size++;
7098019a44ceSStefano Zampini     }
7099019a44ceSStefano Zampini 
7100019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
7101727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
7102727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
7103580bdb30SBarry Smith       ierr = PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7104c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
71050e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
7106580bdb30SBarry Smith         ierr = PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7107727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
7108727cdba6SStefano Zampini       }
71090e6343abSStefano Zampini     }
7110727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
7111b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
711272b8c272SStefano Zampini   }
711372b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
7114727cdba6SStefano Zampini 
7115a717540cSStefano Zampini   /* flush dbg viewer */
7116b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
7117b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7118b8ffe317SStefano Zampini   }
7119a717540cSStefano Zampini 
7120e310c8b4SStefano Zampini   /* free workspace */
7121a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
71224641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
712308122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
71249162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
71259162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
712608122e43SStefano Zampini   } else {
71279162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
71289162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
71299162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
713008122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
713108122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
71329162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
71339162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
713408122e43SStefano Zampini   }
7135674ae819SStefano Zampini   PetscFunctionReturn(0);
7136674ae819SStefano Zampini }
7137674ae819SStefano Zampini 
7138674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
7139674ae819SStefano Zampini {
714071582508SStefano Zampini   ISLocalToGlobalMapping map;
7141674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7142674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
714366da6bd7Sstefano_zampini   PetscInt               i,N;
714466da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
714566da6bd7Sstefano_zampini   PetscErrorCode         ierr;
7146674ae819SStefano Zampini 
7147674ae819SStefano Zampini   PetscFunctionBegin;
71488af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
7149b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
71508e61c736SStefano Zampini     /* Reset previously computed graph */
71518e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
7152674ae819SStefano Zampini     /* Init local Graph struct */
71537fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
715471582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
7155be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
7156674ae819SStefano Zampini 
71577a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
71587a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
71597a0e7b2cSstefano_zampini     }
7160575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
71616080607fSStefano 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",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
71629577ea80SStefano Zampini 
7163674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
716466da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
71654d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
71664d379d7bSStefano Zampini       PetscInt  nvtxs;
7167e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
7168674ae819SStefano Zampini 
71692fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
71702fffb893SStefano Zampini       if (flg_row) {
71714d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
7172b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
71732fffb893SStefano Zampini       }
71742fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
717566da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
7176674ae819SStefano Zampini     }
71779b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
71789b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7179674ae819SStefano Zampini     }
7180674ae819SStefano Zampini 
7181ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
7182ab8c8b98SStefano Zampini       PetscReal    *lcoords;
7183ab8c8b98SStefano Zampini       PetscInt     n;
7184ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
7185ab8c8b98SStefano Zampini 
71864f819b78SStefano Zampini       /* TODO: support for blocked */
7187ab8c8b98SStefano 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);
7188ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
7189ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
7190ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
7191ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
7192ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
7193ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
7194ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
7195ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
7196ab8c8b98SStefano Zampini 
7197ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
7198ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
7199ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
7200ab8c8b98SStefano Zampini     }
7201ab8c8b98SStefano 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);
72021c7a958bSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && !pcbddc->corner_selected);
7203ab8c8b98SStefano Zampini 
7204674ae819SStefano Zampini     /* Setup of Graph */
72054b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
720614f95afaSStefano 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);
7207674ae819SStefano Zampini 
72084f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
72094f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
721020c3699dSStefano Zampini       PetscInt *local_subs,n,totn;
72114f1b2e48SStefano Zampini 
721220c3699dSStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
721320c3699dSStefano Zampini       ierr = PetscMalloc1(n,&local_subs);CHKERRQ(ierr);
721420c3699dSStefano Zampini       for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs;
72154f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
72164f1b2e48SStefano Zampini         const PetscInt *idxs;
72174f1b2e48SStefano Zampini         PetscInt       nl,j;
72184f1b2e48SStefano Zampini 
72194f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
72204f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
722171582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
72224f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
72234f1b2e48SStefano Zampini       }
722420c3699dSStefano Zampini       for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]);
722520c3699dSStefano Zampini       pcbddc->mat_graph->n_local_subs = totn + 1;
72264f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
72274f1b2e48SStefano Zampini     }
72288af8fcf9SStefano Zampini   }
72294f1b2e48SStefano Zampini 
7230cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7231674ae819SStefano Zampini     /* Graph's connected components analysis */
7232674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
723371582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
72344f819b78SStefano Zampini     pcbddc->corner_selected = pcbddc->corner_selection;
72358af8fcf9SStefano Zampini   }
723666da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7237674ae819SStefano Zampini   PetscFunctionReturn(0);
7238674ae819SStefano Zampini }
7239674ae819SStefano Zampini 
7240295df10fSStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[])
72419a7d3425SStefano Zampini {
7242295df10fSStefano Zampini   PetscInt       i,j,n;
72439a7d3425SStefano Zampini   PetscScalar    *alphas;
7244295df10fSStefano Zampini   PetscReal      norm,*onorms;
72459a7d3425SStefano Zampini   PetscErrorCode ierr;
72469a7d3425SStefano Zampini 
72479a7d3425SStefano Zampini   PetscFunctionBegin;
7248295df10fSStefano Zampini   n = *nio;
72498c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
7250295df10fSStefano Zampini   ierr = PetscMalloc2(n,&alphas,n,&onorms);CHKERRQ(ierr);
725192cccca0SStefano Zampini   ierr = VecNormalize(vecs[0],&norm);CHKERRQ(ierr);
725292cccca0SStefano Zampini   if (norm < PETSC_SMALL) {
7253295df10fSStefano Zampini     onorms[0] = 0.0;
725492cccca0SStefano Zampini     ierr = VecSet(vecs[0],0.0);CHKERRQ(ierr);
7255295df10fSStefano Zampini   } else {
7256295df10fSStefano Zampini     onorms[0] = norm;
725792cccca0SStefano Zampini   }
7258295df10fSStefano Zampini 
72598c0031efSStefano Zampini   for (i=1;i<n;i++) {
72608c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
72618c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
72628c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
726392cccca0SStefano Zampini     ierr = VecNormalize(vecs[i],&norm);CHKERRQ(ierr);
726492cccca0SStefano Zampini     if (norm < PETSC_SMALL) {
7265295df10fSStefano Zampini       onorms[i] = 0.0;
726692cccca0SStefano Zampini       ierr = VecSet(vecs[i],0.0);CHKERRQ(ierr);
7267295df10fSStefano Zampini     } else {
7268295df10fSStefano Zampini       onorms[i] = norm;
726992cccca0SStefano Zampini     }
72709a7d3425SStefano Zampini   }
7271295df10fSStefano Zampini   /* push nonzero vectors at the beginning */
7272295df10fSStefano Zampini   for (i=0;i<n;i++) {
7273295df10fSStefano Zampini     if (onorms[i] == 0.0) {
7274295df10fSStefano Zampini       for (j=i+1;j<n;j++) {
7275295df10fSStefano Zampini         if (onorms[j] != 0.0) {
7276295df10fSStefano Zampini           ierr = VecCopy(vecs[j],vecs[i]);CHKERRQ(ierr);
7277295df10fSStefano Zampini           onorms[j] = 0.0;
7278295df10fSStefano Zampini         }
7279295df10fSStefano Zampini       }
7280295df10fSStefano Zampini     }
7281295df10fSStefano Zampini   }
7282295df10fSStefano Zampini   for (i=0,*nio=0;i<n;i++) *nio += onorms[i] != 0.0 ? 1 : 0;
7283295df10fSStefano Zampini   ierr = PetscFree2(alphas,onorms);CHKERRQ(ierr);
72849a7d3425SStefano Zampini   PetscFunctionReturn(0);
72859a7d3425SStefano Zampini }
72869a7d3425SStefano Zampini 
7287bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7288e7931f94SStefano Zampini {
728957de7509SStefano Zampini   Mat            A;
7290e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
7291e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
729252e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
729352e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7294bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
729557de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
729627b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
729727b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
729827b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
729927b6a85dSStefano Zampini   MPI_Comm       subcomm;
730052e5ac9dSStefano Zampini   PetscErrorCode ierr;
7301a57a6d2fSStefano Zampini 
7302e7931f94SStefano Zampini   PetscFunctionBegin;
730357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
730457de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7305fbfcfee5SBarry 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);
730657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
730757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
73086080607fSStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %D",*n_subdomains);
730957de7509SStefano Zampini 
731057de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
731157de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
731257de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
731357de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
731457de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
7315bb360cb4SStefano Zampini   im_active = !!n;
731657de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
731757de7509SStefano Zampini   void_procs = size - active_procs;
731857de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
731957de7509SStefano Zampini   if (void_procs) {
732057de7509SStefano Zampini     PetscInt ncand;
732157de7509SStefano Zampini 
732257de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
732357de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
732457de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
732557de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
732657de7509SStefano Zampini       if (!procs_candidates[i]) {
732757de7509SStefano Zampini         procs_candidates[ncand++] = i;
732857de7509SStefano Zampini       }
732957de7509SStefano Zampini     }
733057de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
733157de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
733257de7509SStefano Zampini   }
733357de7509SStefano Zampini 
7334bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
733514f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
7336bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7337bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
733814f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
733914f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
734014f0bfb9SStefano Zampini     else dest = rank;
734157de7509SStefano Zampini     if (im_active) {
734257de7509SStefano Zampini       issize = 1;
734357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
734414f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
734557de7509SStefano Zampini       } else {
734614f0bfb9SStefano Zampini         isidx = dest;
734757de7509SStefano Zampini       }
734857de7509SStefano Zampini     } else {
734957de7509SStefano Zampini       issize = 0;
735057de7509SStefano Zampini       isidx = -1;
735157de7509SStefano Zampini     }
7352bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
735357de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7354daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
735557de7509SStefano Zampini     PetscFunctionReturn(0);
735657de7509SStefano Zampini   }
7357c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7358c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
735927b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7360e7931f94SStefano Zampini 
7361e7931f94SStefano Zampini   /* Get info on mapping */
73623bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7363e7931f94SStefano Zampini 
7364e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7365785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7366e7931f94SStefano Zampini   xadj[0] = 0;
7367e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7368785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7369785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7370bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
737127b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
737227b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
737327b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7374e7931f94SStefano Zampini 
737527b6a85dSStefano Zampini   xadj_count = 0;
73762b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
737727b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
737827b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7379d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7380d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7381d023bfaeSStefano Zampini         xadj_count++;
738227b6a85dSStefano Zampini         break;
738327b6a85dSStefano Zampini       }
7384e7931f94SStefano Zampini     }
7385e7931f94SStefano Zampini   }
7386d023bfaeSStefano Zampini   xadj[1] = xadj_count;
738727b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
73883bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7389e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7390e7931f94SStefano Zampini 
73913837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7392e7931f94SStefano Zampini 
739327b6a85dSStefano Zampini   /* Restrict work on active processes only */
739427b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
739527b6a85dSStefano Zampini   if (void_procs) {
739627b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
739727b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
739827b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
739927b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
740027b6a85dSStefano Zampini   } else {
740127b6a85dSStefano Zampini     psubcomm = NULL;
740227b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
740327b6a85dSStefano Zampini   }
740427b6a85dSStefano Zampini 
740527b6a85dSStefano Zampini   v_wgt = NULL;
740627b6a85dSStefano Zampini   if (!color) {
7407e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7408e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7409e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7410c8587f34SStefano Zampini   } else {
741152e5ac9dSStefano Zampini     Mat             subdomain_adj;
741252e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
741352e5ac9dSStefano Zampini     MatPartitioning partitioner;
741427b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
741552e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
741657de7509SStefano Zampini     PetscMPIInt     size;
7417b0c7d250SStefano Zampini     PetscBool       aggregate;
7418b0c7d250SStefano Zampini 
741927b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
742027b6a85dSStefano Zampini     if (void_procs) {
742127b6a85dSStefano Zampini       PetscInt prank = rank;
7422785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
742327b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
7424e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7425e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7426c8587f34SStefano Zampini       }
7427e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
742827b6a85dSStefano Zampini     } else {
742927b6a85dSStefano Zampini       oldranks = NULL;
743027b6a85dSStefano Zampini     }
7431b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
743227b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7433b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7434b0c7d250SStefano Zampini       PetscMPIInt nrank;
7435b0c7d250SStefano Zampini       PetscScalar *vals;
7436b0c7d250SStefano Zampini 
743727b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7438b0c7d250SStefano Zampini       lrows = 0;
7439b0c7d250SStefano Zampini       if (nrank<redprocs) {
7440b0c7d250SStefano Zampini         lrows = size/redprocs;
7441b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7442b0c7d250SStefano Zampini       }
744327b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7444b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7445b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7446b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7447b0c7d250SStefano Zampini       row = nrank;
7448b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7449b0c7d250SStefano Zampini       cols = adjncy;
7450b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7451b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7452b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7453b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7454b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
745552e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
745652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
745752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7458b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
745927b6a85dSStefano Zampini       if (use_vwgt) {
746027b6a85dSStefano Zampini         Vec               v;
746127b6a85dSStefano Zampini         const PetscScalar *array;
746227b6a85dSStefano Zampini         PetscInt          nl;
746327b6a85dSStefano Zampini 
746427b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7465bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
746627b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
746727b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
746827b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
746927b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
747027b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
747122db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
747227b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
747327b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
747427b6a85dSStefano Zampini       }
7475b0c7d250SStefano Zampini     } else {
747627b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
747727b6a85dSStefano Zampini       if (use_vwgt) {
747827b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7479bb360cb4SStefano Zampini         v_wgt[0] = n;
748027b6a85dSStefano Zampini       }
7481b0c7d250SStefano Zampini     }
748222b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7483e7931f94SStefano Zampini 
7484e7931f94SStefano Zampini     /* Partition */
748527b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7486ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH)
7487ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH);CHKERRQ(ierr);
7488ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS)
7489ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS);CHKERRQ(ierr);
7490ce64c636SStefano Zampini #else
7491ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE);CHKERRQ(ierr);
7492ce64c636SStefano Zampini #endif
7493e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
749427b6a85dSStefano Zampini     if (v_wgt) {
7495e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7496c8587f34SStefano Zampini     }
749757de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
749857de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7499e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7500e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
750122b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7502e7931f94SStefano Zampini 
750352e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
75046583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
750552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
750652e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
750757de7509SStefano Zampini     if (!aggregate) {
750857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
750927b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
751027b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
751127b6a85dSStefano Zampini #endif
751257de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
751327b6a85dSStefano Zampini       } else if (oldranks) {
7514b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
751527b6a85dSStefano Zampini       } else {
751627b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
751757de7509SStefano Zampini       }
751828143c3dSStefano Zampini     } else {
75197fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7520b0c7d250SStefano Zampini       PetscMPIInt tag;
7521b0c7d250SStefano Zampini       MPI_Request *reqs;
7522b0c7d250SStefano Zampini 
7523b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7524b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7525b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
752627b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
752728143c3dSStefano Zampini       }
75287fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7529b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7530b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
753157de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
753227b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
753327b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
753427b6a85dSStefano Zampini #endif
75357fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
753627b6a85dSStefano Zampini       } else if (oldranks) {
75377fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
753827b6a85dSStefano Zampini       } else {
75397fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7540e7931f94SStefano Zampini       }
754157de7509SStefano Zampini     }
754252e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7543e7931f94SStefano Zampini     /* clean up */
7544e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
754552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7546e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7547e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7548e7931f94SStefano Zampini   }
754927b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
755057de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7551e7931f94SStefano Zampini 
7552e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7553e7931f94SStefano Zampini   i = 1;
755427b6a85dSStefano Zampini   if (!color) i=0;
755557de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7556e7931f94SStefano Zampini   PetscFunctionReturn(0);
7557e7931f94SStefano Zampini }
7558e7931f94SStefano Zampini 
7559e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7560e7931f94SStefano Zampini 
75611e0482f5SStefano 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[])
7562e7931f94SStefano Zampini {
756370cf5478SStefano Zampini   Mat                    local_mat;
7564e7931f94SStefano Zampini   IS                     is_sends_internal;
75659d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
75661ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
75679d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7568e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7569e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7570e7931f94SStefano Zampini   const PetscInt*        is_indices;
7571e7931f94SStefano Zampini   MatType                new_local_type;
7572e7931f94SStefano Zampini   /* buffers */
7573e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
757428143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
75759d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
75761683a169SBarry Smith   PetscScalar            *ptr_vals,*recv_buffer_vals;
75771683a169SBarry Smith   const PetscScalar      *send_buffer_vals;
75781ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7579e7931f94SStefano Zampini   /* MPI */
758028143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
758128143c3dSStefano Zampini   PetscSubcomm           subcomm;
7582e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
758328143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
758428143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
75851ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
75861ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
75871ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7588e7931f94SStefano Zampini   PetscErrorCode         ierr;
7589e7931f94SStefano Zampini 
7590e7931f94SStefano Zampini   PetscFunctionBegin;
759157de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7592e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7593fbfcfee5SBarry 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);
759457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
759557de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
759657de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
759757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
759857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
75991ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
76001ae86dd6SStefano Zampini   if (nvecs) {
76011ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
76021ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
76031ae86dd6SStefano Zampini   }
760457de7509SStefano Zampini   /* further checks */
7605e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7606e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7607e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7608e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7609e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
761057de7509SStefano Zampini   if (reuse && *mat_n) {
761170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
761257de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
761370cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
761428143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
761570cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
761670cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
761770cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
761870cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
761970cf5478SStefano Zampini   }
7620e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7621e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
762257de7509SStefano Zampini 
7623e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7624e7931f94SStefano Zampini   if (!is_sends) {
762528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7626bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7627c8587f34SStefano Zampini   } else {
7628e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7629e7931f94SStefano Zampini     is_sends_internal = is_sends;
7630c8587f34SStefano Zampini   }
7631e7931f94SStefano Zampini 
7632e7931f94SStefano Zampini   /* get comm */
7633a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7634e7931f94SStefano Zampini 
7635e7931f94SStefano Zampini   /* compute number of sends */
7636e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7637e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7638e7931f94SStefano Zampini 
7639e7931f94SStefano Zampini   /* compute number of receives */
7640e569e4e1SStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
7641e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&iflags);CHKERRQ(ierr);
7642580bdb30SBarry Smith   ierr = PetscArrayzero(iflags,size);CHKERRQ(ierr);
7643e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7644e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7645e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7646e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7647e7931f94SStefano Zampini 
764828143c3dSStefano Zampini   /* restrict comm if requested */
764928143c3dSStefano Zampini   subcomm = 0;
765028143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
765128143c3dSStefano Zampini   if (restrict_comm) {
7652779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7653779c1cceSStefano Zampini 
765428143c3dSStefano Zampini     color = 0;
765553a05cb3SStefano Zampini     if (restrict_full) {
765653a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
765753a05cb3SStefano Zampini     } else {
765853a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
765953a05cb3SStefano Zampini     }
7660b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
7661e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
766228143c3dSStefano Zampini     /* check if reuse has been requested */
766357de7509SStefano Zampini     if (reuse) {
766428143c3dSStefano Zampini       if (*mat_n) {
766528143c3dSStefano Zampini         PetscMPIInt subcommsize2;
766628143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
766728143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
766828143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
766928143c3dSStefano Zampini       } else {
767028143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
767128143c3dSStefano Zampini       }
767228143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7673779c1cceSStefano Zampini       PetscMPIInt rank;
7674779c1cceSStefano Zampini 
7675779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
767628143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
767728143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
767828143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7679306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
768028143c3dSStefano Zampini     }
768128143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
768228143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
768328143c3dSStefano Zampini   } else {
768428143c3dSStefano Zampini     comm_n = comm;
768528143c3dSStefano Zampini   }
768628143c3dSStefano Zampini 
7687e7931f94SStefano Zampini   /* prepare send/receive buffers */
7688e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_idxs);CHKERRQ(ierr);
7689580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_idxs,size);CHKERRQ(ierr);
7690e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_vals);CHKERRQ(ierr);
7691580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_vals,size);CHKERRQ(ierr);
769228143c3dSStefano Zampini   if (nis) {
7693e569e4e1SStefano Zampini     ierr = PetscCalloc1(size,&ilengths_idxs_is);CHKERRQ(ierr);
769428143c3dSStefano Zampini   }
7695e7931f94SStefano Zampini 
769628143c3dSStefano Zampini   /* Get data from local matrices */
76976c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7698e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7699e7931f94SStefano Zampini     /*
7700e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7701e7931f94SStefano Zampini        send_buffer_idxs should contain:
7702e7931f94SStefano Zampini        - MatType_PRIVATE type
7703e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7704e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7705e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7706e7931f94SStefano Zampini     */
77076c4ed002SBarry Smith   else {
77081683a169SBarry Smith     ierr = MatDenseGetArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
77093bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7710854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7711e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7712e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
77133bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7714580bdb30SBarry Smith     ierr = PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i);CHKERRQ(ierr);
77153bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7716e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7717e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7718e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7719e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7720c8587f34SStefano Zampini     }
7721c8587f34SStefano Zampini   }
7722e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
772328143c3dSStefano Zampini   /* additional is (if any) */
772428143c3dSStefano Zampini   if (nis) {
772528143c3dSStefano Zampini     PetscMPIInt psum;
772628143c3dSStefano Zampini     PetscInt j;
772728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
772828143c3dSStefano Zampini       PetscInt plen;
772928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
773028143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
773128143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
773228143c3dSStefano Zampini     }
7733854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
773428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
773528143c3dSStefano Zampini       PetscInt plen;
773628143c3dSStefano Zampini       const PetscInt *is_array_idxs;
773728143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
773828143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
773928143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
7740580bdb30SBarry Smith       ierr = PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen);CHKERRQ(ierr);
774128143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
774228143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
774328143c3dSStefano Zampini     }
774428143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
774528143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
774628143c3dSStefano Zampini     }
774728143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
774828143c3dSStefano Zampini   }
77493b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
775028143c3dSStefano Zampini 
7751e7931f94SStefano Zampini   buf_size_idxs = 0;
7752e7931f94SStefano Zampini   buf_size_vals = 0;
775328143c3dSStefano Zampini   buf_size_idxs_is = 0;
77541ae86dd6SStefano Zampini   buf_size_vecs = 0;
7755e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7756e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7757e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
775828143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
77591ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7760e7931f94SStefano Zampini   }
7761785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7762785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
776395ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
77641ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7765e7931f94SStefano Zampini 
7766e7931f94SStefano Zampini   /* get new tags for clean communications */
7767e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7768e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
776928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
77701ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7771e7931f94SStefano Zampini 
7772e7931f94SStefano Zampini   /* allocate for requests */
7773785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7774785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
777595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
77761ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7777785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7778785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
777995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
77801ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7781e7931f94SStefano Zampini 
7782e7931f94SStefano Zampini   /* communications */
7783e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7784e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
778528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
77861ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7787e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7788e7931f94SStefano Zampini     source_dest = onodes[i];
7789e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7790e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7791e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7792e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
779328143c3dSStefano Zampini     if (nis) {
779457de7509SStefano Zampini       source_dest = onodes_is[i];
779528143c3dSStefano 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);
779628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
779728143c3dSStefano Zampini     }
77981ae86dd6SStefano Zampini     if (nvecs) {
77991ae86dd6SStefano Zampini       source_dest = onodes[i];
78001ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
78011ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
78021ae86dd6SStefano Zampini     }
7803e7931f94SStefano Zampini   }
7804e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7805e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7806e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7807ba2698f1SMatthew G. Knepley     ierr = MPI_Isend((PetscScalar*)send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
780828143c3dSStefano Zampini     if (nis) {
780928143c3dSStefano 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);
781028143c3dSStefano Zampini     }
78111ae86dd6SStefano Zampini     if (nvecs) {
78121ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
78131ae86dd6SStefano 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);
78141ae86dd6SStefano Zampini     }
7815e7931f94SStefano Zampini   }
7816e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7817e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7818e7931f94SStefano Zampini 
7819e7931f94SStefano Zampini   /* assemble new l2g map */
7820e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7821e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78229d30be91SStefano Zampini   new_local_rows = 0;
7823e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
78249d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7825e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7826e7931f94SStefano Zampini   }
78279d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7828e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78299d30be91SStefano Zampini   new_local_rows = 0;
7830e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7831580bdb30SBarry Smith     ierr = PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1));CHKERRQ(ierr);
78329d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7833e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7834e7931f94SStefano Zampini   }
78359d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
78369d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7837e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7838e7931f94SStefano Zampini 
7839e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7840e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7841e7931f94SStefano 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) */
7842e7931f94SStefano Zampini   if (n_recvs) {
784328143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7844e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7845e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7846e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7847e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7848e7931f94SStefano Zampini         break;
7849e7931f94SStefano Zampini       }
7850e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7851e7931f94SStefano Zampini     }
7852e7931f94SStefano Zampini     switch (new_local_type_private) {
785328143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7854e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7855e7931f94SStefano Zampini         bs = 1;
7856e7931f94SStefano Zampini         break;
7857e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7858e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7859e7931f94SStefano Zampini         bs = 1;
7860e7931f94SStefano Zampini         break;
7861e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7862e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7863e7931f94SStefano Zampini         break;
7864e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7865e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7866e7931f94SStefano Zampini         break;
7867e7931f94SStefano Zampini       default:
7868fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7869e7931f94SStefano Zampini         break;
7870e7931f94SStefano Zampini     }
7871ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7872ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
787328143c3dSStefano Zampini     bs = 1;
7874e7931f94SStefano Zampini   }
7875e7931f94SStefano Zampini 
787670cf5478SStefano Zampini   /* create MATIS object if needed */
787757de7509SStefano Zampini   if (!reuse) {
7878e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7879e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
788070cf5478SStefano Zampini   } else {
788170cf5478SStefano Zampini     /* it also destroys the local matrices */
788257de7509SStefano Zampini     if (*mat_n) {
788370cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
788457de7509SStefano Zampini     } else { /* this is a fake object */
788557de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
788657de7509SStefano Zampini     }
788770cf5478SStefano Zampini   }
788870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7889e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
78909d30be91SStefano Zampini 
78919d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
78929d30be91SStefano Zampini 
78939d30be91SStefano Zampini   /* Global to local map of received indices */
78949d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
78959d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
78969d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
78979d30be91SStefano Zampini 
78989d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
78999d30be91SStefano Zampini   buf_size_idxs = 0;
79009d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
79019d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
79029d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
79039d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
79049d30be91SStefano Zampini   }
79059d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
79069d30be91SStefano Zampini 
79079d30be91SStefano Zampini   /* set preallocation */
79089d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
79099d30be91SStefano Zampini   if (!newisdense) {
79109d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
79119d30be91SStefano Zampini 
79129d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
79139d30be91SStefano Zampini     if (n_recvs) {
79149d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
79159d30be91SStefano Zampini     }
79169d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
79179d30be91SStefano Zampini       PetscInt j;
79189d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
79199d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
79209d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
79219d30be91SStefano Zampini         }
79229d30be91SStefano Zampini       } else {
79239d30be91SStefano Zampini         /* TODO */
79249d30be91SStefano Zampini       }
79259d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
79269d30be91SStefano Zampini     }
79279d30be91SStefano Zampini     if (new_local_nnz) {
79289d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
79299d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
79309d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
79319d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
79329d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
79339d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
79349d30be91SStefano Zampini     } else {
79359d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
79369d30be91SStefano Zampini     }
79379d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
79389d30be91SStefano Zampini   } else {
79399d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
79409d30be91SStefano Zampini   }
7941e7931f94SStefano Zampini 
7942e7931f94SStefano Zampini   /* set values */
7943e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
79449d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7945e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7946e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7947e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
79489d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7949e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7950e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7951e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
795228143c3dSStefano Zampini     } else {
795328143c3dSStefano Zampini       /* TODO */
7954e7931f94SStefano Zampini     }
7955e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7956e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7957e7931f94SStefano Zampini   }
7958e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7959e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79603b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
796170cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796270cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79639d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7964e7931f94SStefano Zampini 
7965dfd14d43SStefano Zampini #if 0
796628143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7967e7931f94SStefano Zampini     Vec       lvec,rvec;
7968e7931f94SStefano Zampini     PetscReal infty_error;
7969e7931f94SStefano Zampini 
79702a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7971e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7972e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7973e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
797470cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7975e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7976e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7977e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7978e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7979e7931f94SStefano Zampini   }
798028143c3dSStefano Zampini #endif
7981e7931f94SStefano Zampini 
798228143c3dSStefano Zampini   /* assemble new additional is (if any) */
798328143c3dSStefano Zampini   if (nis) {
798428143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
798528143c3dSStefano Zampini 
798628143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7987854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
798828143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
798928143c3dSStefano Zampini     psum = 0;
799028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
799128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
799228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
799328143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
799428143c3dSStefano Zampini         psum += plen;
799528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
799628143c3dSStefano Zampini       }
799728143c3dSStefano Zampini     }
7998854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7999854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
800028143c3dSStefano Zampini     for (i=1;i<nis;i++) {
800128143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
800228143c3dSStefano Zampini     }
8003580bdb30SBarry Smith     ierr = PetscArrayzero(count_is,nis);CHKERRQ(ierr);
800428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
800528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
800628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
800728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
8008580bdb30SBarry Smith         ierr = PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen);CHKERRQ(ierr);
800928143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
801028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
801128143c3dSStefano Zampini       }
801228143c3dSStefano Zampini     }
801328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
801428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
8015c3b366b1Sprj-       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);
801628143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
801728143c3dSStefano Zampini     }
801828143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
801928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
802028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
802128143c3dSStefano Zampini   }
8022e7931f94SStefano Zampini   /* free workspace */
802328143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
8024e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
8025e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
8026e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
8027e7931f94SStefano Zampini   if (isdense) {
8028e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
80291683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
80303b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
8031e7931f94SStefano Zampini   } else {
8032e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
8033e7931f94SStefano Zampini   }
803428143c3dSStefano Zampini   if (nis) {
803528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
803628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
803728143c3dSStefano Zampini   }
80381ae86dd6SStefano Zampini 
80391ae86dd6SStefano Zampini   if (nvecs) {
80401ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
80411ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
80421ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80431ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
80441ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
80451ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
80461ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
80471ae86dd6SStefano Zampini     /* set values */
80481ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
80491ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
80501ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80511ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
80521ae86dd6SStefano Zampini       PetscInt j;
80531ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
80541ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
80551ae86dd6SStefano Zampini       }
80561ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
80571ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
80581ae86dd6SStefano Zampini     }
80591ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80601ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
80611ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
80621ae86dd6SStefano Zampini   }
80631ae86dd6SStefano Zampini 
80641ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
80651ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
8066e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
8067e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
80681ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
806928143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
8070e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
8071e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
80721ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
807328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
8074e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
8075e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
8076e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
8077e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
8078e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
807928143c3dSStefano Zampini   if (nis) {
808028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
808128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
808228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
808328143c3dSStefano Zampini   }
808428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
808528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
808628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
808728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
808828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
808928143c3dSStefano Zampini     }
80901ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
80911ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
80921ae86dd6SStefano Zampini     }
809353a05cb3SStefano Zampini     *mat_n = NULL;
809428143c3dSStefano Zampini   }
8095e7931f94SStefano Zampini   PetscFunctionReturn(0);
8096e7931f94SStefano Zampini }
8097a57a6d2fSStefano Zampini 
809812edc857SStefano Zampini /* temporary hack into ksp private data structure */
8099af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
810012edc857SStefano Zampini 
8101c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
8102c8587f34SStefano Zampini {
8103c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
8104c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
810520a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
81061ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
81071e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
81089881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
810920a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
81104f819b78SStefano Zampini   IS                     coarse_is,*isarray,corners;
81116e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
811230368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
8113e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
8114f9eb5b7dSStefano Zampini   PC                     pc_temp;
8115c8587f34SStefano Zampini   PCType                 coarse_pc_type;
8116c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
8117f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
81187274672aSStefano Zampini   PetscBool              coarse_reuse;
81191e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
812068457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
812122bc73bbSStefano Zampini   PetscScalar            *array;
812257de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
812357de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
8124e569e4e1SStefano Zampini   PetscMPIInt            size;
81259881197aSStefano Zampini   PetscErrorCode         ierr;
8126fdc09c96SStefano Zampini 
8127c8587f34SStefano Zampini   PetscFunctionBegin;
812843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8129c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
813068457ee5SStefano 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 */
8131fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
81325a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
81337de4f681Sstefano_zampini 
81347de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
8135fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
8136f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
8137f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
8138f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
8139fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
814051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
814151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
8142727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
8143fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
8144fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
8145fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
8146f4ddd8eeSStefano Zampini       }
8147fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
8148fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
8149f4ddd8eeSStefano Zampini     }
815070cf5478SStefano Zampini     /* reset any subassembling information */
815157de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
815270cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
815357de7509SStefano Zampini     }
81546e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
8155fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
8156f4ddd8eeSStefano Zampini   }
815757de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
815857de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
815957de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
816057de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
816118a45a71SStefano Zampini   } else {
816257de7509SStefano Zampini     coarse_mat = NULL;
816357de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
81646e683305SStefano Zampini   }
8165e7931f94SStefano Zampini 
8166abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
8167abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
8168abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
8169abbbba34SStefano Zampini 
8170abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
81714f819b78SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense);CHKERRQ(ierr);
8172e176bc59SStefano 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);
81736e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
81746e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
81756e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8176abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
8177abbbba34SStefano Zampini 
817857de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
817957de7509SStefano Zampini   im_active = !!(pcis->n);
818057de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
818157de7509SStefano Zampini 
818214f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
818328d58a37SPierre Jolivet   /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */
818457de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
8185e569e4e1SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
818657de7509SStefano Zampini   coarse_mat_is        = NULL;
818757de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
818857de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
8189e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
8190ce64c636SStefano Zampini   if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size;
819157de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
8192e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
819357de7509SStefano Zampini   if (multilevel_requested) {
819457de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
819557de7509SStefano Zampini     restr      = PETSC_FALSE;
819657de7509SStefano Zampini     full_restr = PETSC_FALSE;
819757de7509SStefano Zampini   } else {
8198e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
819957de7509SStefano Zampini     restr      = PETSC_TRUE;
820057de7509SStefano Zampini     full_restr = PETSC_TRUE;
820157de7509SStefano Zampini   }
8202e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
820357de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
820457de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
8205a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
8206bb360cb4SStefano Zampini       if (multilevel_requested) {
8207bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8208bb360cb4SStefano Zampini       } else {
8209bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8210bb360cb4SStefano Zampini       }
8211a198735bSStefano Zampini     } else {
82127de4f681Sstefano_zampini       PetscMPIInt rank;
821328d58a37SPierre Jolivet 
8214a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
8215e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
8216a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
8217a198735bSStefano Zampini     }
821857de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
821957de7509SStefano Zampini     PetscInt    psum;
822057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
822157de7509SStefano Zampini     else psum = 0;
822257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8223075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
822457de7509SStefano Zampini   }
822557de7509SStefano Zampini   /* determine if we can go multilevel */
822657de7509SStefano Zampini   if (multilevel_requested) {
822757de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
822857de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
822957de7509SStefano Zampini   }
823057de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
823157de7509SStefano Zampini 
8232e4d548c7SStefano Zampini   /* dump subassembling pattern */
8233e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
8234e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
8235e4d548c7SStefano Zampini   }
82366e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
82371e0482f5SStefano Zampini   nedcfield = -1;
82384f819b78SStefano Zampini   corners = NULL;
82398966356dSPierre Jolivet   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */
82406e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
82416e683305SStefano Zampini     const PetscInt         *idxs;
82426e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
82436e683305SStefano Zampini 
82446e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
82450be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
82466e683305SStefano Zampini     /* allocate space for temporary storage */
8247854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
8248854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
82496e683305SStefano Zampini     /* allocate for IS array */
82506e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
82511e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
82521e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
82531e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
82541e0482f5SStefano Zampini       } else {
82551e0482f5SStefano Zampini         nedcfield = 0;
82566080607fSStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%D)",nisdofs);
82571e0482f5SStefano Zampini         nisdofs = 1;
82581e0482f5SStefano Zampini       }
82591e0482f5SStefano Zampini     }
82606e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
826127b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
826230368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
8263854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
82646e683305SStefano Zampini     /* dofs splitting */
82656e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
82666e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
82671e0482f5SStefano Zampini       if (nedcfield != i) {
82686e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
82696e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
82706e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
82716e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
82721e0482f5SStefano Zampini       } else {
82731e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
82741e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
82751e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
82766080607fSStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %D != %D",tsize,nout);
82771e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
82781e0482f5SStefano Zampini       }
82796e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
828030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
82816e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
82826e683305SStefano Zampini     }
82836e683305SStefano Zampini     /* neumann boundaries */
82846e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
82856e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
82866e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
82876e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
82886e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
82896e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
82906e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
829130368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
82926e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
82936e683305SStefano Zampini     }
82944f819b78SStefano Zampini     /* coordinates */
82954f819b78SStefano Zampini     if (pcbddc->corner_selected) {
82964f819b78SStefano Zampini       ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
82974f819b78SStefano Zampini       ierr = ISGetLocalSize(corners,&tsize);CHKERRQ(ierr);
82984f819b78SStefano Zampini       ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
82994f819b78SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
83004f819b78SStefano Zampini       if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %D != %D",tsize,nout);
83014f819b78SStefano Zampini       ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
83024f819b78SStefano Zampini       ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
83034f819b78SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
83044f819b78SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners);CHKERRQ(ierr);
83054f819b78SStefano Zampini     }
83066e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
83076e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
83086e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
83096e683305SStefano Zampini   } else {
83106e683305SStefano Zampini     nis = 0;
83116e683305SStefano Zampini     nisdofs = 0;
83126e683305SStefano Zampini     nisneu = 0;
831330368db7SStefano Zampini     nisvert = 0;
83146e683305SStefano Zampini     isarray = NULL;
83156e683305SStefano Zampini   }
83166e683305SStefano Zampini   /* destroy no longer needed map */
83176e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
83186e683305SStefano Zampini 
831957de7509SStefano Zampini   /* subassemble */
832057de7509SStefano Zampini   if (multilevel_allowed) {
83211ae86dd6SStefano Zampini     Vec       vp[1];
83221ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
832357de7509SStefano Zampini     PetscBool reuse,reuser;
83241ae86dd6SStefano Zampini 
832557de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
832657de7509SStefano Zampini     else reuse = PETSC_FALSE;
832757de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
83281ae86dd6SStefano Zampini     vp[0] = NULL;
83291ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
83301ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
83311ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
83321ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
83331ae86dd6SStefano Zampini       nvecs = 1;
83341ae86dd6SStefano Zampini 
83351ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8336a198735bSStefano Zampini         Mat      B,loc_divudotp;
83371ae86dd6SStefano Zampini         Vec      v,p;
83381ae86dd6SStefano Zampini         IS       dummy;
83391ae86dd6SStefano Zampini         PetscInt np;
83401ae86dd6SStefano Zampini 
8341a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8342a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
83431ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
83447dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
83451ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
83461ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
83471ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
83481ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
83491ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
83501ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
83511ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
83521ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
83531ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
83541ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
83551ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
83561ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
835774e2c79eSStefano Zampini       }
83581ae86dd6SStefano Zampini     }
83591ae86dd6SStefano Zampini     if (reuser) {
83601e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
836174e2c79eSStefano Zampini     } else {
83621e0482f5SStefano 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);
83631ae86dd6SStefano Zampini     }
83641ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
83651683a169SBarry Smith       PetscScalar       *arraym;
83661683a169SBarry Smith       const PetscScalar *arrayv;
83671ae86dd6SStefano Zampini       PetscInt          nl;
83681ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
83691ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
83701ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
83711683a169SBarry Smith       ierr = VecGetArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
8372580bdb30SBarry Smith       ierr = PetscArraycpy(arraym,arrayv,nl);CHKERRQ(ierr);
83731683a169SBarry Smith       ierr = VecRestoreArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
83741ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
83751ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8376a198735bSStefano Zampini     } else {
8377a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
83781ae86dd6SStefano Zampini     }
83791ae86dd6SStefano Zampini   } else {
83801e0482f5SStefano 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);
83816e683305SStefano Zampini   }
838257de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
838357de7509SStefano Zampini     if (!multilevel_allowed) {
8384487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
83856e683305SStefano Zampini     } else {
838657de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
838757de7509SStefano Zampini       if (coarse_mat_is) {
838857de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
838957de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
839057de7509SStefano Zampini         coarse_mat = coarse_mat_is;
839157de7509SStefano Zampini       }
8392779c1cceSStefano Zampini     }
8393779c1cceSStefano Zampini   }
839457de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
839557de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
83966e683305SStefano Zampini 
83976e683305SStefano Zampini   /* create local to global scatters for coarse problem */
839868457ee5SStefano Zampini   if (compute_vecs) {
83996e683305SStefano Zampini     PetscInt lrows;
84006e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
840157de7509SStefano Zampini     if (coarse_mat) {
840257de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
84036e683305SStefano Zampini     } else {
84046e683305SStefano Zampini       lrows = 0;
84056e683305SStefano Zampini     }
84066e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
84076e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
840889535278SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD);CHKERRQ(ierr);
84096e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
84109448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
84116e683305SStefano Zampini   }
84126e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8413c8587f34SStefano Zampini 
8414f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8415f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8416f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8417f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8418f9eb5b7dSStefano Zampini   } else {
8419f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8420f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8421c8587f34SStefano Zampini   }
8422c8587f34SStefano Zampini 
84236e683305SStefano Zampini   /* print some info if requested */
84246e683305SStefano Zampini   if (pcbddc->dbg_flag) {
84256e683305SStefano Zampini     if (!multilevel_allowed) {
84266e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
84276e683305SStefano Zampini       if (multilevel_requested) {
84286080607fSStefano 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);
84296e683305SStefano Zampini       } else if (pcbddc->max_levels) {
84306080607fSStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%D)\n",pcbddc->max_levels);CHKERRQ(ierr);
84316e683305SStefano Zampini       }
84326e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
84336e683305SStefano Zampini     }
84346e683305SStefano Zampini   }
84356e683305SStefano Zampini 
84361e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
84371e0482f5SStefano Zampini   coarseG = NULL;
84381e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
84391e0482f5SStefano Zampini     MPI_Comm ccomm;
84401e0482f5SStefano Zampini     if (coarse_mat) {
84411e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
84421e0482f5SStefano Zampini     } else {
84431e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
84441e0482f5SStefano Zampini     }
84451e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
84461e0482f5SStefano Zampini   }
84471e0482f5SStefano Zampini 
8448f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
844957de7509SStefano Zampini   if (coarse_mat) {
845028d58a37SPierre Jolivet     PetscBool   isredundant,isbddc,force,valid;
84516a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
84527274672aSStefano Zampini 
84536e683305SStefano Zampini     if (pcbddc->dbg_flag) {
845457de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
84556e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
84566e683305SStefano Zampini     }
8457f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8458312be037SStefano Zampini       char   prefix[256],str_level[16];
8459e604994aSStefano Zampini       size_t len;
84601e0482f5SStefano Zampini 
846157de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8462422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8463c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8464f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
846557de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8466c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
84676e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8468c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
84691e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8470c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8471e604994aSStefano Zampini       /* prefix */
8472e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8473e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8474e604994aSStefano Zampini       if (!pcbddc->current_level) {
8475a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8476a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8477c8587f34SStefano Zampini       } else {
8478e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8479312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8480312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8481a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
848234d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
848335529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8484a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8485e604994aSStefano Zampini       }
8486e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
84873e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
84883e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
84893e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
84903e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8491f9eb5b7dSStefano Zampini       /* allow user customization */
8492f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
8493e569e4e1SStefano Zampini       /* get some info after set from options */
8494e569e4e1SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
849528d58a37SPierre Jolivet       /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
849628d58a37SPierre Jolivet       force = PETSC_FALSE;
849728d58a37SPierre Jolivet       ierr = PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL);CHKERRQ(ierr);
849828d58a37SPierre Jolivet       ierr = PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"");CHKERRQ(ierr);
8499e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
850028d58a37SPierre Jolivet       if (multilevel_allowed && !force && !valid) {
8501e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
8502e569e4e1SStefano Zampini         ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8503e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
8504e569e4e1SStefano Zampini         ierr   = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
8505e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
85064f819b78SStefano Zampini         if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */
85074f819b78SStefano Zampini           ierr = PetscObjectOptionsBegin((PetscObject)pc_temp);CHKERRQ(ierr);
85084f819b78SStefano Zampini           ierr = (*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp);CHKERRQ(ierr);
85094f819b78SStefano Zampini           ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp);CHKERRQ(ierr);
85104f819b78SStefano Zampini           ierr = PetscOptionsEnd();CHKERRQ(ierr);
85114f819b78SStefano Zampini           pc_temp->setfromoptionscalled++;
85124f819b78SStefano Zampini         }
8513e569e4e1SStefano Zampini       }
85143e3c6dadSStefano Zampini     }
85153e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
851651bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
85173e3c6dadSStefano Zampini     if (nisdofs) {
85183e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
85193e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
85203e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
85213e3c6dadSStefano Zampini       }
85223e3c6dadSStefano Zampini     }
85233e3c6dadSStefano Zampini     if (nisneu) {
85243e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
85253e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8526312be037SStefano Zampini     }
852730368db7SStefano Zampini     if (nisvert) {
852830368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
852930368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
853030368db7SStefano Zampini     }
85311e0482f5SStefano Zampini     if (coarseG) {
85321e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
85331e0482f5SStefano Zampini     }
8534f9eb5b7dSStefano Zampini 
8535f9eb5b7dSStefano Zampini     /* get some info after set from options */
8536f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
85374f819b78SStefano Zampini 
8538b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8539b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8540f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8541f9eb5b7dSStefano Zampini     }
854228d58a37SPierre Jolivet     /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
854328d58a37SPierre Jolivet     force = PETSC_FALSE;
854428d58a37SPierre Jolivet     ierr = PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL);CHKERRQ(ierr);
854528d58a37SPierre Jolivet     ierr = PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"");CHKERRQ(ierr);
854628d58a37SPierre Jolivet     if (multilevel_requested && multilevel_allowed && !valid && !force) {
8547b76f3995Sstefano_zampini       ierr = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8548b76f3995Sstefano_zampini     }
85497274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
85504f3a063dSStefano Zampini     if (isredundant) {
85514f3a063dSStefano Zampini       KSP inner_ksp;
85524f3a063dSStefano Zampini       PC  inner_pc;
85539326c5c6Sstefano_zampini 
85544f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
85554f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
85564f3a063dSStefano Zampini     }
8557f9eb5b7dSStefano Zampini 
855857de7509SStefano Zampini     /* parameters which miss an API */
85597274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
856057de7509SStefano Zampini     if (isbddc) {
8561720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
85627274672aSStefano Zampini 
8563720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
856457de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8565e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
856627b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
856727b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8568a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8569a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8570a198735bSStefano Zampini         IS                     row,col;
8571a198735bSStefano Zampini         const PetscInt         *gidxs;
8572a198735bSStefano Zampini         PetscInt               n,st,M,N;
8573a198735bSStefano Zampini 
8574a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8575a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8576a198735bSStefano Zampini         st   = st-n;
8577a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8578a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8579a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8580a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8581a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8582a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8583a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8584a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8585a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8586a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8587a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8588a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8589a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8590a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8591a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8592a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8593a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8594a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8595a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8596a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
85978ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8598a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8599720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8600bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8601720d30f9SStefano Zampini       }
8602d4d8cf7bSStefano Zampini     }
86039881197aSStefano Zampini 
86043301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
86055a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
86063301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
86073301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
86083301b35fSStefano Zampini     }
86093301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
86103301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
86113301b35fSStefano Zampini     }
86123301b35fSStefano Zampini     if (pc->pmat->spd_set) {
86133301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
86143301b35fSStefano Zampini     }
861527b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
861627b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
861727b6a85dSStefano Zampini     }
86186e683305SStefano Zampini     /* set operators */
861904fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
86203007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix);CHKERRQ(ierr);
86215f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
86226e683305SStefano Zampini     if (pcbddc->dbg_flag) {
86236e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
86246e683305SStefano Zampini     }
86256e683305SStefano Zampini   }
86261e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
86276e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8628b1ecc7b1SStefano Zampini #if 0
8629b9b85e73SStefano Zampini   {
8630b9b85e73SStefano Zampini     PetscViewer viewer;
8631b9b85e73SStefano Zampini     char filename[256];
8632b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8633b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
86346a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8635b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8636f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8637b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8638b9b85e73SStefano Zampini   }
8639b9b85e73SStefano Zampini #endif
8640f9eb5b7dSStefano Zampini 
86414f819b78SStefano Zampini   if (corners) {
86424f819b78SStefano Zampini     Vec            gv;
86434f819b78SStefano Zampini     IS             is;
86444f819b78SStefano Zampini     const PetscInt *idxs;
86454f819b78SStefano Zampini     PetscInt       i,d,N,n,cdim = pcbddc->mat_graph->cdim;
86464f819b78SStefano Zampini     PetscScalar    *coords;
86474f819b78SStefano Zampini 
86484f819b78SStefano Zampini     if (!pcbddc->mat_graph->cloc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates");
86494f819b78SStefano Zampini     ierr = VecGetSize(pcbddc->coarse_vec,&N);CHKERRQ(ierr);
86504f819b78SStefano Zampini     ierr = VecGetLocalSize(pcbddc->coarse_vec,&n);CHKERRQ(ierr);
86514f819b78SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv);CHKERRQ(ierr);
86524f819b78SStefano Zampini     ierr = VecSetBlockSize(gv,cdim);CHKERRQ(ierr);
86534f819b78SStefano Zampini     ierr = VecSetSizes(gv,n*cdim,N*cdim);CHKERRQ(ierr);
86544f819b78SStefano Zampini     ierr = VecSetType(gv,VECSTANDARD);CHKERRQ(ierr);
86554f819b78SStefano Zampini     ierr = VecSetFromOptions(gv);CHKERRQ(ierr);
86564f819b78SStefano Zampini     ierr = VecSet(gv,PETSC_MAX_REAL);CHKERRQ(ierr); /* we only propagate coordinates from vertices constraints */
86574f819b78SStefano Zampini 
86584f819b78SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
86594f819b78SStefano Zampini     ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
86604f819b78SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
86614f819b78SStefano Zampini     ierr = PetscMalloc1(n*cdim,&coords);CHKERRQ(ierr);
86624f819b78SStefano Zampini     for (i=0;i<n;i++) {
86634f819b78SStefano Zampini       for (d=0;d<cdim;d++) {
86644f819b78SStefano Zampini         coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d];
86654f819b78SStefano Zampini       }
86664f819b78SStefano Zampini     }
86674f819b78SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
86684f819b78SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
86694f819b78SStefano Zampini 
86704f819b78SStefano Zampini     ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
86714f819b78SStefano Zampini     ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
86724f819b78SStefano Zampini     ierr = VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES);CHKERRQ(ierr);
86734f819b78SStefano Zampini     ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
86744f819b78SStefano Zampini     ierr = PetscFree(coords);CHKERRQ(ierr);
86754f819b78SStefano Zampini     ierr = VecAssemblyBegin(gv);CHKERRQ(ierr);
86764f819b78SStefano Zampini     ierr = VecAssemblyEnd(gv);CHKERRQ(ierr);
86774f819b78SStefano Zampini     ierr = VecGetArray(gv,&coords);CHKERRQ(ierr);
86784f819b78SStefano Zampini     if (pcbddc->coarse_ksp) {
86794f819b78SStefano Zampini       PC        coarse_pc;
86804f819b78SStefano Zampini       PetscBool isbddc;
86814f819b78SStefano Zampini 
86824f819b78SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
86834f819b78SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
86844f819b78SStefano Zampini       if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */
86854f819b78SStefano Zampini         PetscReal *realcoords;
86864f819b78SStefano Zampini 
86874f819b78SStefano Zampini         ierr = VecGetLocalSize(gv,&n);CHKERRQ(ierr);
86884f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86894f819b78SStefano Zampini         ierr = PetscMalloc1(n,&realcoords);CHKERRQ(ierr);
86904f819b78SStefano Zampini         for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]);
86914f819b78SStefano Zampini #else
86924f819b78SStefano Zampini         realcoords = coords;
86934f819b78SStefano Zampini #endif
86944f819b78SStefano Zampini         ierr = PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords);CHKERRQ(ierr);
86954f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86964f819b78SStefano Zampini         ierr = PetscFree(realcoords);CHKERRQ(ierr);
86974f819b78SStefano Zampini #endif
86984f819b78SStefano Zampini       }
86994f819b78SStefano Zampini     }
87004f819b78SStefano Zampini     ierr = VecRestoreArray(gv,&coords);CHKERRQ(ierr);
87014f819b78SStefano Zampini     ierr = VecDestroy(&gv);CHKERRQ(ierr);
87024f819b78SStefano Zampini   }
87034f819b78SStefano Zampini   ierr = ISDestroy(&corners);CHKERRQ(ierr);
87044f819b78SStefano Zampini 
870598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
870698a51de6SStefano Zampini     Vec crhs,csol;
870704708bb6SStefano Zampini 
8708f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8709f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8710f347579bSStefano Zampini     if (!csol) {
87112a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8712f9eb5b7dSStefano Zampini     }
8713f347579bSStefano Zampini     if (!crhs) {
87142a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8715f347579bSStefano Zampini     }
8716b0f5fe93SStefano Zampini   }
87171ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8718b0f5fe93SStefano Zampini 
8719b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8720b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8721b0f5fe93SStefano Zampini 
8722b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
87234f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
87244f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
87254f1b2e48SStefano Zampini     }
8726b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8727b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8728b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8729b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8730b0f5fe93SStefano Zampini     if (coarse_mat) {
8731b0f5fe93SStefano Zampini       Vec         nullv;
8732b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8733b0f5fe93SStefano Zampini       PetscInt    nl;
8734b0f5fe93SStefano Zampini 
8735b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8736b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8737b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8738b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8739580bdb30SBarry Smith       ierr = PetscArraycpy(array2,array,nl);CHKERRQ(ierr);
8740b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8741b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8742b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8743b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8744b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8745b0f5fe93SStefano Zampini     }
8746b0f5fe93SStefano Zampini   }
874743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8748b0f5fe93SStefano Zampini 
874943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8750b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8751b0f5fe93SStefano Zampini     PetscBool ispreonly;
8752b0f5fe93SStefano Zampini 
8753b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8754b0f5fe93SStefano Zampini       PetscBool isnull;
8755b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8756bef83e63SStefano Zampini       if (isnull) {
8757b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8758b0f5fe93SStefano Zampini       }
8759bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8760b0f5fe93SStefano Zampini     }
8761b0f5fe93SStefano Zampini     /* setup coarse ksp */
8762b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8763cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8764cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
87656e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8766c8587f34SStefano Zampini       KSP       check_ksp;
87672b510759SStefano Zampini       KSPType   check_ksp_type;
8768c8587f34SStefano Zampini       PC        check_pc;
87696e683305SStefano Zampini       Vec       check_vec,coarse_vec;
87706a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
87712b510759SStefano Zampini       PetscInt  its;
87726e683305SStefano Zampini       PetscBool compute_eigs;
87736e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
87746e683305SStefano Zampini       PetscInt  neigs;
87758e185a42SStefano Zampini       const char *prefix;
8776c8587f34SStefano Zampini 
87772b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
87786e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
877915579a77SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0);CHKERRQ(ierr);
8780399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
878123ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8782f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8783e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8784e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8785e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
87862b510759SStefano Zampini       if (ispreonly) {
87872b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
87886e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
87892b510759SStefano Zampini       } else {
8790cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
87916e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8792c8587f34SStefano Zampini       }
8793c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
87946e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
87956e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
87966e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8797a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8798a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8799a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8800a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8801c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8802c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8803c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8804c8587f34SStefano Zampini       /* create random vec */
88052701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8806c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
88076e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8808c8587f34SStefano Zampini       /* solve coarse problem */
88096e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8810c0decd05SBarry Smith       ierr = KSPCheckSolve(check_ksp,pc,coarse_vec);CHKERRQ(ierr);
8811cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
88126e683305SStefano Zampini       if (compute_eigs) {
8813854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8814854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
88156e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
88161ae86dd6SStefano Zampini         if (neigs) {
88176e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
88186e683305SStefano Zampini           lambda_min = eigs_r[0];
88196e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
88202701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
88212701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8822cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8823cbcc2c2aSStefano Zampini             }
8824c8587f34SStefano Zampini           }
8825c8587f34SStefano Zampini         }
88261ae86dd6SStefano Zampini       }
8827cbcc2c2aSStefano Zampini 
8828c8587f34SStefano Zampini       /* check coarse problem residual error */
88296e683305SStefano Zampini       if (pcbddc->dbg_flag) {
88306e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
88316e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
88326e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8833c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
88346e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
88356e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8836779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
88376e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
88386e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
88396e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
88406e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8841b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8842b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8843b0f5fe93SStefano Zampini         }
88446e683305SStefano Zampini         if (compute_eigs) {
88456e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8846b03ebc13SStefano Zampini           KSPConvergedReason reason;
8847deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8848c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8849b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
88506e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8851b03ebc13SStefano 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);
88526e683305SStefano Zampini           for (i=0;i<neigs;i++) {
88536e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8854c8587f34SStefano Zampini           }
88556e683305SStefano Zampini         }
88566e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
88576e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
88586e683305SStefano Zampini       }
8859e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
88602701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8861c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
88626e683305SStefano Zampini       if (compute_eigs) {
88636e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
88646e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8865c8587f34SStefano Zampini       }
88666e683305SStefano Zampini     }
88676e683305SStefano Zampini   }
8868bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8869cbcc2c2aSStefano Zampini   /* print additional info */
8870cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
88716e683305SStefano Zampini     /* waits until all processes reaches this point */
88726e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
88736080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %D\n",pcbddc->current_level);CHKERRQ(ierr);
8874cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8875cbcc2c2aSStefano Zampini   }
8876cbcc2c2aSStefano Zampini 
88772b510759SStefano Zampini   /* free memory */
8878fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
887943371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8880c8587f34SStefano Zampini   PetscFunctionReturn(0);
8881c8587f34SStefano Zampini }
8882674ae819SStefano Zampini 
8883f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8884f34684f1SStefano Zampini {
8885f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8886f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8887f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8888dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8889dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
889073be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8891dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8892f34684f1SStefano Zampini   PetscErrorCode ierr;
8893f34684f1SStefano Zampini 
8894f34684f1SStefano Zampini   PetscFunctionBegin;
8895f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
88966c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8897dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
88983bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8899dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8900dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
89016583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8902dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8903dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8904dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
89056c4ed002SBarry 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);
8906dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8907dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8908580bdb30SBarry Smith   ierr = PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size);CHKERRQ(ierr);
8909dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8910dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8911f34684f1SStefano Zampini 
8912f34684f1SStefano Zampini   /* check numbering */
8913f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8914019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8915dc456d91SStefano Zampini     PetscInt    i;
8916b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8917f34684f1SStefano Zampini 
8918f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8919f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8920f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
89211575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8922019a44ceSStefano Zampini     /* counter */
8923019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8924019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8925019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8926019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8927019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8928019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8929f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8930f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8931727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8932f34684f1SStefano Zampini     }
8933f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8934f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8935f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8936e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8937e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8938e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8939e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8940f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8941019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8942f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8943019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
89442c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
894575c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8946b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
89472c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
89486080607fSStefano 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);
8949f34684f1SStefano Zampini       }
8950f34684f1SStefano Zampini     }
8951019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8952b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8953f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8954f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8955f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8956f34684f1SStefano Zampini     }
8957f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8958f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8959e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8960e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8961f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
89626080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %D (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8963b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8964ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8965ca8b9ea9SStefano Zampini 
8966ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
89673bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8968f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8969f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8970f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8971f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
89726080607fSStefano 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);
8973f34684f1SStefano Zampini       }
8974f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8975ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8976f34684f1SStefano Zampini     }
8977f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
89781575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8979302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8980f34684f1SStefano Zampini   }
89816080607fSStefano Zampini 
8982f34684f1SStefano Zampini   /* get back data */
8983f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8984f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8985674ae819SStefano Zampini   PetscFunctionReturn(0);
8986674ae819SStefano Zampini }
8987674ae819SStefano Zampini 
8988a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8989e456f2a8SStefano Zampini {
8990e456f2a8SStefano Zampini   IS             localis_t;
8991a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8992e456f2a8SStefano Zampini   PetscScalar    *vals;
8993e456f2a8SStefano Zampini   PetscErrorCode ierr;
8994e456f2a8SStefano Zampini 
8995e456f2a8SStefano Zampini   PetscFunctionBegin;
8996a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8997e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8998854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8999e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
9000e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
9001a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
9002a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
90031035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
90043151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
9005a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
90061035eff8SStefano Zampini   }
9007a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
9008e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
9009e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
9010a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
9011a7dc3881SStefano Zampini   /* now compute set in local ordering */
9012a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9013a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9014a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
9015a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
9016a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9017ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9018e456f2a8SStefano Zampini       lsize++;
9019e456f2a8SStefano Zampini     }
9020e456f2a8SStefano Zampini   }
9021854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
9022a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9023ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9024e456f2a8SStefano Zampini       idxs[lsize++] = i;
9025e456f2a8SStefano Zampini     }
9026e456f2a8SStefano Zampini   }
9027a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
9028a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
9029e456f2a8SStefano Zampini   *localis = localis_t;
9030e456f2a8SStefano Zampini   PetscFunctionReturn(0);
9031e456f2a8SStefano Zampini }
9032906d46d4SStefano Zampini 
903308122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
9034b96c3477SStefano Zampini {
9035a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9036b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9037b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
9038a64f4aa4SStefano Zampini   Mat                 S_j;
9039b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
9040b96c3477SStefano Zampini   PetscBool           free_used_adj;
9041b96c3477SStefano Zampini   PetscErrorCode      ierr;
9042b96c3477SStefano Zampini 
9043b96c3477SStefano Zampini   PetscFunctionBegin;
904443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
9045b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
9046b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
904708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
9048b96c3477SStefano Zampini     used_xadj = NULL;
9049b96c3477SStefano Zampini     used_adjncy = NULL;
9050b96c3477SStefano Zampini   } else {
905108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
905208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
905308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
905408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
9055b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
9056b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
9057b96c3477SStefano Zampini     } else {
90582fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
9059b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
9060b96c3477SStefano Zampini       PetscInt       nvtxs;
9061b96c3477SStefano Zampini 
90622fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
90632fffb893SStefano Zampini       if (flg_row) {
9064b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
9065580bdb30SBarry Smith         ierr = PetscArraycpy(used_xadj,xadj,nvtxs+1);CHKERRQ(ierr);
9066580bdb30SBarry Smith         ierr = PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
9067b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
90682fffb893SStefano Zampini       } else {
90692fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
90702fffb893SStefano Zampini         used_xadj = NULL;
90712fffb893SStefano Zampini         used_adjncy = NULL;
90722fffb893SStefano Zampini       }
90732fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
9074b96c3477SStefano Zampini     }
9075b96c3477SStefano Zampini   }
9076d5574798SStefano Zampini 
9077d5574798SStefano Zampini   /* setup sub_schurs data */
90782f37b69bSStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
9079df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
9080df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
9081a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
908291af6908SStefano 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);
9083a64f4aa4SStefano Zampini   } else {
908472b8c272SStefano Zampini     Mat       change = NULL;
90859d54b7f4SStefano Zampini     Vec       scaling = NULL;
9086111315fdSstefano_zampini     IS        change_primal = NULL, iP;
9087111315fdSstefano_zampini     PetscInt  benign_n;
9088111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
90897ebab0bbSStefano Zampini     PetscBool need_change = PETSC_FALSE;
9090111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
9091a3df083aSStefano Zampini 
90925feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
90935feab87aSStefano Zampini       PetscInt n_vertices;
90945feab87aSStefano Zampini 
90955feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
90962034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
90975feab87aSStefano Zampini     }
9098a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
9099a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
9100ca92afb2SStefano Zampini     } else {
9101a3df083aSStefano Zampini       benign_n = 0;
9102ca92afb2SStefano Zampini     }
9103b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
9104b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
9105b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
910672b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
910722db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
9108b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
910922db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
9110b7ab4a40SStefano Zampini     }
9111b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
9112b7ab4a40SStefano 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 */
9113b7ab4a40SStefano Zampini     if (need_change) {
911488c03ad3SStefano Zampini       PC_IS   *pcisf;
911588c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
911688c03ad3SStefano Zampini       PC      pcf;
911788c03ad3SStefano Zampini 
9118e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
911988c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
912088c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
912188c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
9122b9be95fcSstefano_zampini 
912388c03ad3SStefano Zampini       /* hacks */
912488c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
912572b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
912672b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
912772b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
912872b8c272SStefano Zampini       pcisf->n                     = pcis->n;
912972b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
913088c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
913188c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
913288c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
913388c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
913488c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
913588c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
913672b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
913788c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
9138b9be95fcSstefano_zampini 
9139b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
914088c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
914172b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
914272b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
914372b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
914472b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
9145b9be95fcSstefano_zampini 
914688c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
914772b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
914888c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
914988c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
915088c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
915188c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
915288c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
915388c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
9154b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
915588c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
915688c03ad3SStefano Zampini     }
91579d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
9158111315fdSstefano_zampini 
9159111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
9160111315fdSstefano_zampini     if (iP) {
9161111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
9162111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
9163111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
9164111315fdSstefano_zampini     }
9165111315fdSstefano_zampini     if (discrete_harmonic) {
9166111315fdSstefano_zampini       Mat A;
9167111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
9168111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
9169111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
9170111315fdSstefano_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);
9171111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
9172111315fdSstefano_zampini     } else {
917391af6908SStefano 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);
9174111315fdSstefano_zampini     }
917572b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
917672b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
9177ca92afb2SStefano Zampini   }
9178d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9179b96c3477SStefano Zampini 
9180b96c3477SStefano Zampini   /* free adjacency */
9181b96c3477SStefano Zampini   if (free_used_adj) {
9182b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
9183b96c3477SStefano Zampini   }
918443371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
9185b96c3477SStefano Zampini   PetscFunctionReturn(0);
9186b96c3477SStefano Zampini }
9187b96c3477SStefano Zampini 
918808122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
9189b96c3477SStefano Zampini {
9190b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9191b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9192b96c3477SStefano Zampini   PCBDDCGraph         graph;
9193b96c3477SStefano Zampini   PetscErrorCode      ierr;
9194b96c3477SStefano Zampini 
9195b96c3477SStefano Zampini   PetscFunctionBegin;
9196b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
919708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
91983301b35fSStefano Zampini     IS       verticesIS,verticescomm;
91993301b35fSStefano Zampini     PetscInt vsize,*idxs;
9200b96c3477SStefano Zampini 
9201b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
92023301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
92033301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
92043301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
92053301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
9206c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
9207b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
9208be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
9209441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
92103301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
9211b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
9212b96c3477SStefano Zampini   } else {
9213b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
9214b96c3477SStefano Zampini   }
9215e4d548c7SStefano Zampini   /* print some info */
92165c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
9217e4d548c7SStefano Zampini     IS       vertices;
9218e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
9219c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
9220e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9221e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
9222e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9223e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
92246080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,(int)nv,pcbddc->use_vertices);CHKERRQ(ierr);
92256080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,(int)nedges,pcbddc->use_edges);CHKERRQ(ierr);
92266080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,(int)nfaces,pcbddc->use_faces);CHKERRQ(ierr);
9227e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
9228e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9229c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9230e4d548c7SStefano Zampini   }
9231b96c3477SStefano Zampini 
9232b96c3477SStefano Zampini   /* sub_schurs init */
9233b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
9234b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
9235b334f244SStefano Zampini   }
923688113c35SStefano 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);
9237a64f4aa4SStefano Zampini 
9238b96c3477SStefano Zampini   /* free graph struct */
923908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
9240b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
9241b96c3477SStefano Zampini   }
9242b96c3477SStefano Zampini   PetscFunctionReturn(0);
9243b96c3477SStefano Zampini }
9244fa34dd3eSStefano Zampini 
9245fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
9246fa34dd3eSStefano Zampini {
9247fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9248fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9249fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
9250fa34dd3eSStefano Zampini 
9251fa34dd3eSStefano Zampini   PetscFunctionBegin;
9252fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
9253fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
92544f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
9255fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
92564f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
925775c01103SStefano Zampini     PetscReal      norm;
9258fa34dd3eSStefano Zampini     PetscInt       i;
9259fa34dd3eSStefano Zampini 
9260fa34dd3eSStefano Zampini     /* B0 and B0_B */
9261fa34dd3eSStefano Zampini     if (zerodiag) {
9262fa34dd3eSStefano Zampini       IS       dummy;
9263fa34dd3eSStefano Zampini 
92644f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
92657dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
9266fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
9267fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
9268fa34dd3eSStefano Zampini     }
9269fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
9270fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
9271fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
9272fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9273fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9274fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9275fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9276fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
9277fa34dd3eSStefano Zampini     /* S_j */
92782f37b69bSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
9279fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
9280fa34dd3eSStefano Zampini 
9281fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
9282fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
9283fa34dd3eSStefano Zampini     /* continuous in primal space */
9284fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
9285fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9286fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9287fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
92884f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
92894f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
9290fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9291fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9292fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9293fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9294fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9295fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9296fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
9297fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
9298fa34dd3eSStefano Zampini 
9299fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
9300fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
9301fa34dd3eSStefano Zampini     /* local with Schur */
9302fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
9303fa34dd3eSStefano Zampini     if (zerodiag) {
9304fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
93054f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
9306fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9307fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
9308fa34dd3eSStefano Zampini     }
9309fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
9310fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9311fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9312fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9313fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9314fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
9315fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9316fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9317fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
9318fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9319fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9320fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9321fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9322fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9323fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
9324fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
9325fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9326fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9327fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9328fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9329fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9330fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9331fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9332fa34dd3eSStefano Zampini     if (zerodiag) {
9333fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
9334fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
93354f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
9336fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9337fa34dd3eSStefano Zampini     }
9338fa34dd3eSStefano Zampini     /* BDDC */
9339fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
9340fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
9341fa34dd3eSStefano Zampini 
9342fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
9343fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
9344fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
93456080607fSStefano Zampini     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);CHKERRQ(ierr);
93464f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
93476080607fSStefano Zampini       ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%D] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));CHKERRQ(ierr);
9348fa34dd3eSStefano Zampini     }
93494f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
9350fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
9351fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
9352fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
9353fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9354fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
9355fa34dd3eSStefano Zampini   }
9356fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9357fa34dd3eSStefano Zampini }
93581e0482f5SStefano Zampini 
93591e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
93601e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
93611e0482f5SStefano Zampini {
93621e0482f5SStefano Zampini   Mat            At;
93631e0482f5SStefano Zampini   IS             rows;
93641e0482f5SStefano Zampini   PetscInt       rst,ren;
93651e0482f5SStefano Zampini   PetscErrorCode ierr;
93661e0482f5SStefano Zampini   PetscLayout    rmap;
93671e0482f5SStefano Zampini 
93681e0482f5SStefano Zampini   PetscFunctionBegin;
93691e0482f5SStefano Zampini   rst = ren = 0;
93701e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93711e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
93721e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
93731e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
93741e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
93751e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
93761e0482f5SStefano Zampini   }
9377e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
93787dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
93791e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
93801e0482f5SStefano Zampini 
93811e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93821e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
93831e0482f5SStefano Zampini     IS         from,to;
93841e0482f5SStefano Zampini     Vec        gvec;
93851e0482f5SStefano Zampini     PetscInt   lsize;
93861e0482f5SStefano Zampini 
93871e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
93881e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
93891e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
93901e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
93911e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
93921e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
93931e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
93941e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
93951e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
93961e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
93971e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
93981e0482f5SStefano Zampini     b->A = a->A;
93991e0482f5SStefano Zampini     b->B = a->B;
94001e0482f5SStefano Zampini 
94011e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
94021e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
94031e0482f5SStefano Zampini     b->rowindices      = 0;
94041e0482f5SStefano Zampini     b->rowvalues       = 0;
94051e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
94061e0482f5SStefano Zampini 
94071e0482f5SStefano Zampini     (*B)->rmap         = rmap;
94081e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
94091e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
94101e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
94111e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
94121e0482f5SStefano Zampini 
94131e0482f5SStefano Zampini     if (a->colmap) {
94141e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
94151e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
94161e0482f5SStefano Zampini #else
94171e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
94181e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
9419580bdb30SBarry Smith       ierr = PetscArraycpy(b->colmap,a->colmap,At->cmap->N);CHKERRQ(ierr);
94201e0482f5SStefano Zampini #endif
94211e0482f5SStefano Zampini     } else b->colmap = 0;
94221e0482f5SStefano Zampini     if (a->garray) {
94231e0482f5SStefano Zampini       PetscInt len;
94241e0482f5SStefano Zampini       len  = a->B->cmap->n;
94251e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
94261e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
9427580bdb30SBarry Smith       if (len) { ierr = PetscArraycpy(b->garray,a->garray,len);CHKERRQ(ierr); }
94281e0482f5SStefano Zampini     } else b->garray = 0;
94291e0482f5SStefano Zampini 
94301e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
94311e0482f5SStefano Zampini     b->lvec = a->lvec;
94321e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
94331e0482f5SStefano Zampini 
94341e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
94351e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
94361e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
94371e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
94381e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
94399448b7f1SJunchao Zhang     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
94401e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
94411e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
94421e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
94431e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
94441e0482f5SStefano Zampini   }
94451e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
94461e0482f5SStefano Zampini   PetscFunctionReturn(0);
94471e0482f5SStefano Zampini }
9448