xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 580bdb303e1ee3b1222b2042810b4c26340259c6)
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);
68*580bdb30SBarry 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);
72*580bdb30SBarry 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 
236*580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
237*580bdb30SBarry 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) */
323*580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
324*580bdb30SBarry 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);
637*580bdb30SBarry Smith   ierr = PetscArrayzero(sfvleaves,nv);CHKERRQ(ierr);
638*580bdb30SBarry 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 */
803*580bdb30SBarry 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);
936*580bdb30SBarry 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 */
1031*580bdb30SBarry 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;
1139*580bdb30SBarry 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);
1183*580bdb30SBarry 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);
16046a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16056a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16066a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16076a8fc67bSStefano Zampini     }
16086a8fc67bSStefano Zampini     goto boundary;
16096a8fc67bSStefano Zampini   }
16105c5e10d6SStefano Zampini 
16111f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16121f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16131f4df5f7SStefano Zampini       PetscInt i;
16140c85b387SStefano Zampini 
16151f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16161f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16170c85b387SStefano Zampini         PetscInt bs;
16180c85b387SStefano Zampini 
16191f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16200c85b387SStefano Zampini         ierr = ISGetBlockSize(pcbddc->ISForDofs[i],&bs);CHKERRQ(ierr);
16210c85b387SStefano Zampini         ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
16221f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16231f4df5f7SStefano Zampini       }
16241f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16251f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16261f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16271f4df5f7SStefano Zampini     }
16281f4df5f7SStefano Zampini   } else {
162921ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
163021ef3d20SStefano Zampini       DM dm;
163121ef3d20SStefano Zampini 
163221ef3d20SStefano Zampini       ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
16334f819b78SStefano Zampini       if (!dm) {
16344f819b78SStefano Zampini         ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
163521ef3d20SStefano Zampini       }
163621ef3d20SStefano Zampini       if (dm) {
163721ef3d20SStefano Zampini         IS      *fields;
163821ef3d20SStefano Zampini         PetscInt nf,i;
16390c85b387SStefano Zampini 
164021ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
164121ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
164221ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16430c85b387SStefano Zampini           PetscInt bs;
16440c85b387SStefano Zampini 
164521ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16460c85b387SStefano Zampini           ierr = ISGetBlockSize(fields[i],&bs);CHKERRQ(ierr);
16470c85b387SStefano Zampini           ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
164821ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
164921ef3d20SStefano Zampini         }
165021ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
165121ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
165221ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
165321ef3d20SStefano Zampini         PetscContainer   c;
165421ef3d20SStefano Zampini 
165521ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
165621ef3d20SStefano Zampini         if (c) {
165721ef3d20SStefano Zampini           MatISLocalFields lf;
165821ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
165921ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
166021ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16611f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1662986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
166321ef3d20SStefano Zampini           if (i > 1) {
1664986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16651f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16661f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16671f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16681f4df5f7SStefano Zampini             }
16691f4df5f7SStefano Zampini           }
167021ef3d20SStefano Zampini         }
167121ef3d20SStefano Zampini       }
16727a0e7b2cSstefano_zampini     } else {
16737a0e7b2cSstefano_zampini       PetscInt i;
16747a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16757a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16767a0e7b2cSstefano_zampini       }
16771f4df5f7SStefano Zampini     }
1678986cdee1SStefano Zampini   }
16791f4df5f7SStefano Zampini 
16805c5e10d6SStefano Zampini boundary:
16811f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16821f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16837a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16847a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16851f4df5f7SStefano Zampini   }
16861f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16871f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16887a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16897a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16901f4df5f7SStefano Zampini   }
16911f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16921f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16931f4df5f7SStefano Zampini   }
16941f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16951f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16967620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16977620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16987620a527SStefano Zampini     IS        primalv = NULL;
16997620a527SStefano Zampini     PetscInt  i;
17008361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
17017a0e7b2cSstefano_zampini 
17027620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17037620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17047620a527SStefano Zampini     }
17057620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17068361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17077620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17087620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17097620a527SStefano Zampini   }
17107620a527SStefano Zampini   /* early stage corner detection */
17117620a527SStefano Zampini   {
17127620a527SStefano Zampini     DM dm;
17137620a527SStefano Zampini 
17147620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17154f819b78SStefano Zampini     if (!dm) {
17164f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17174f819b78SStefano Zampini     }
17187620a527SStefano Zampini     if (dm) {
17197620a527SStefano Zampini       PetscBool isda;
17207620a527SStefano Zampini 
17217620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17227620a527SStefano Zampini       if (isda) {
17237620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17247620a527SStefano Zampini         IS                     corners;
17257620a527SStefano Zampini         Mat                    lA;
17264f819b78SStefano Zampini         PetscBool              gl,lo;
17277620a527SStefano Zampini 
17284f819b78SStefano Zampini         {
17294f819b78SStefano Zampini           Vec               cvec;
17304f819b78SStefano Zampini           const PetscScalar *coords;
17314f819b78SStefano Zampini           PetscInt          dof,n,cdim;
17324f819b78SStefano Zampini           PetscBool         memc = PETSC_TRUE;
17334f819b78SStefano Zampini 
17344f819b78SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17354f819b78SStefano Zampini           ierr = DMGetCoordinates(dm,&cvec);CHKERRQ(ierr);
17364f819b78SStefano Zampini           ierr = VecGetLocalSize(cvec,&n);CHKERRQ(ierr);
17374f819b78SStefano Zampini           ierr = VecGetBlockSize(cvec,&cdim);CHKERRQ(ierr);
17384f819b78SStefano Zampini           n   /= cdim;
17394f819b78SStefano Zampini           ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
17404f819b78SStefano Zampini           ierr = PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords);CHKERRQ(ierr);
17414f819b78SStefano Zampini           ierr = VecGetArrayRead(cvec,&coords);CHKERRQ(ierr);
17424f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17434f819b78SStefano Zampini           memc = PETSC_FALSE;
17444f819b78SStefano Zampini #endif
17454f819b78SStefano Zampini           if (dof != 1) memc = PETSC_FALSE;
17464f819b78SStefano Zampini           if (memc) {
1747*580bdb30SBarry Smith             ierr = PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof);CHKERRQ(ierr);
17484f819b78SStefano Zampini           } else { /* BDDC graph does not use any blocked information, we need to replicate the data */
17494f819b78SStefano Zampini             PetscReal *bcoords = pcbddc->mat_graph->coords;
17504f819b78SStefano Zampini             PetscInt  i, b, d;
17514f819b78SStefano Zampini 
17524f819b78SStefano Zampini             for (i=0;i<n;i++) {
17534f819b78SStefano Zampini               for (b=0;b<dof;b++) {
17544f819b78SStefano Zampini                 for (d=0;d<cdim;d++) {
17554f819b78SStefano Zampini                   bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]);
17564f819b78SStefano Zampini                 }
17574f819b78SStefano Zampini               }
17584f819b78SStefano Zampini             }
17594f819b78SStefano Zampini           }
17604f819b78SStefano Zampini           ierr = VecRestoreArrayRead(cvec,&coords);CHKERRQ(ierr);
17614f819b78SStefano Zampini           pcbddc->mat_graph->cdim  = cdim;
17624f819b78SStefano Zampini           pcbddc->mat_graph->cnloc = dof*n;
17634f819b78SStefano Zampini           pcbddc->mat_graph->cloc  = PETSC_FALSE;
17644f819b78SStefano Zampini         }
1765d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17667620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17677620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17687620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17694f819b78SStefano Zampini         lo   = (PetscBool)(l2l && corners);
17704f819b78SStefano Zampini         ierr = MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
17714f819b78SStefano Zampini         if (gl) { /* From PETSc's DMDA */
17727620a527SStefano Zampini           const PetscInt    *idx;
177372ed36d8SStefano Zampini           PetscInt          dof,bs,*idxout,n;
17747620a527SStefano Zampini 
177572ed36d8SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17767620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17777620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17787620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
177972ed36d8SStefano Zampini           if (bs == dof) {
17807620a527SStefano Zampini             ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17817620a527SStefano Zampini             ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
178272ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
178372ed36d8SStefano Zampini             PetscInt i,d;
178472ed36d8SStefano Zampini 
178572ed36d8SStefano Zampini             ierr = PetscMalloc1(dof*n,&idxout);CHKERRQ(ierr);
178672ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
178772ed36d8SStefano Zampini             ierr = ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout);CHKERRQ(ierr);
178872ed36d8SStefano Zampini 
178972ed36d8SStefano Zampini             bs = 1;
179072ed36d8SStefano Zampini             n *= dof;
179172ed36d8SStefano Zampini           }
17927620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1793d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17947620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17957620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17967620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17971c7a958bSStefano Zampini           pcbddc->corner_selected  = PETSC_TRUE;
17984f819b78SStefano Zampini           pcbddc->corner_selection = PETSC_TRUE;
17994f819b78SStefano Zampini         }
18004f819b78SStefano Zampini         if (corners) {
1801d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
18027620a527SStefano Zampini         }
18037620a527SStefano Zampini       }
18047620a527SStefano Zampini     }
18057620a527SStefano Zampini   }
18061c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
18071c7a958bSStefano Zampini     DM dm;
18081c7a958bSStefano Zampini 
18091c7a958bSStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
18104f819b78SStefano Zampini     if (!dm) {
18114f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
18121c7a958bSStefano Zampini     }
18134f819b78SStefano Zampini     if (dm) { /* this can get very expensive, I need to find a faster alternative */
18141c7a958bSStefano Zampini       Vec            vcoords;
18151c7a958bSStefano Zampini       PetscSection   section;
18161c7a958bSStefano Zampini       PetscReal      *coords;
18171c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
18181c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
18191c7a958bSStefano Zampini 
18201c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
1821e87a4003SBarry Smith       ierr = DMGetSection(dm,&section);CHKERRQ(ierr);
18221c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
18231c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
18241c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
18251c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
18261c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
18271c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
18281c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
18291c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
18301c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
18311c7a958bSStefano Zampini         PetscInt          i;
18321c7a958bSStefano Zampini         const PetscScalar *v;
18331c7a958bSStefano Zampini 
18341c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
18351c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
18361c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
18371c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
18381c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
18391c7a958bSStefano Zampini       }
18401c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
18411c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
18421c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
18431c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
18441c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
18451c7a958bSStefano Zampini     }
18461c7a958bSStefano Zampini   }
18477a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18487a0e7b2cSstefano_zampini }
18497a0e7b2cSstefano_zampini 
18507a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18517a0e7b2cSstefano_zampini {
18527a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18537a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
18547a0e7b2cSstefano_zampini   IS              nis;
18557a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18567a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18577a0e7b2cSstefano_zampini   PetscBool       *ld;
18587a0e7b2cSstefano_zampini 
18597a0e7b2cSstefano_zampini   PetscFunctionBegin;
18607a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18617a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18627a0e7b2cSstefano_zampini     /* init rootdata with true */
18637a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
18647a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
18657a0e7b2cSstefano_zampini   } else {
1866*580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
18677a0e7b2cSstefano_zampini   }
1868*580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
18697a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18707a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18717a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18727a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18737a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18747a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18757a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18767a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18777a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18787a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18797a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18807a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18817a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18827a0e7b2cSstefano_zampini   } else {
18837a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18847a0e7b2cSstefano_zampini   }
18857a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18867a0e7b2cSstefano_zampini     if (ld[i])
18877a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18887a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18897a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18907a0e7b2cSstefano_zampini   *is  = nis;
18911f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18921f4df5f7SStefano Zampini }
18931f4df5f7SStefano Zampini 
18943e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18953e589ea0SStefano Zampini {
18963e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18973e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18983e589ea0SStefano Zampini   PetscErrorCode    ierr;
18993e589ea0SStefano Zampini 
19003e589ea0SStefano Zampini   PetscFunctionBegin;
19013e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
19023e589ea0SStefano Zampini     PetscFunctionReturn(0);
19033e589ea0SStefano Zampini   }
19043e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19053e589ea0SStefano Zampini     Vec swap;
19063e589ea0SStefano Zampini 
19073e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19083e589ea0SStefano Zampini     swap = pcbddc->work_change;
19093e589ea0SStefano Zampini     pcbddc->work_change = r;
19103e589ea0SStefano Zampini     r = swap;
19113e589ea0SStefano Zampini   }
19123e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19133e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19143e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1915c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19163e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
19173e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19183e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19193e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1920f913dca9SStefano Zampini     pcbddc->work_change = r;
19213e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19223e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19233e589ea0SStefano Zampini   }
19243e589ea0SStefano Zampini   PetscFunctionReturn(0);
19253e589ea0SStefano Zampini }
19263e589ea0SStefano Zampini 
1927a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1928a3df083aSStefano Zampini {
1929a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1930a3df083aSStefano Zampini   PetscErrorCode          ierr;
1931a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1932a3df083aSStefano Zampini 
1933a3df083aSStefano Zampini   PetscFunctionBegin;
1934a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1935a3df083aSStefano Zampini   if (transpose) {
1936a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1937a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1938a3df083aSStefano Zampini   } else {
1939a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1940a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1941a3df083aSStefano Zampini   }
1942a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1943a3df083aSStefano Zampini   if (apply_right) {
1944a3df083aSStefano Zampini     const PetscScalar *ax;
1945a3df083aSStefano Zampini     PetscInt          nl,i;
1946a3df083aSStefano Zampini 
1947a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1948a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1949*580bdb30SBarry Smith     ierr = PetscArraycpy(ctx->work,ax,nl);CHKERRQ(ierr);
1950a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1951a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1952a3df083aSStefano Zampini       PetscScalar    sum,val;
1953a3df083aSStefano Zampini       const PetscInt *idxs;
1954a3df083aSStefano Zampini       PetscInt       nz,j;
1955a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1956a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1957a3df083aSStefano Zampini       sum = 0.;
1958a3df083aSStefano Zampini       if (ctx->apply_p0) {
1959a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1960a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1961a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1962a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1963a3df083aSStefano Zampini         }
1964a3df083aSStefano Zampini       } else {
1965a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1966a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1967a3df083aSStefano Zampini         }
1968a3df083aSStefano Zampini       }
1969a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1970a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1971a3df083aSStefano Zampini     }
1972a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1973a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1974a3df083aSStefano Zampini   }
1975a3df083aSStefano Zampini   if (transpose) {
1976a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1977a3df083aSStefano Zampini   } else {
1978a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1979a3df083aSStefano Zampini   }
1980a3df083aSStefano Zampini   if (reset_x) {
1981a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1982a3df083aSStefano Zampini   }
1983a3df083aSStefano Zampini   if (apply_left) {
1984a3df083aSStefano Zampini     PetscScalar *ay;
1985a3df083aSStefano Zampini     PetscInt    i;
1986a3df083aSStefano Zampini 
1987a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1988a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1989a3df083aSStefano Zampini       PetscScalar    sum,val;
1990a3df083aSStefano Zampini       const PetscInt *idxs;
1991a3df083aSStefano Zampini       PetscInt       nz,j;
1992a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1993a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1994a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1995a3df083aSStefano Zampini       if (ctx->apply_p0) {
1996a3df083aSStefano Zampini         sum = 0.;
1997a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1998a3df083aSStefano Zampini           sum += ay[idxs[j]];
1999a3df083aSStefano Zampini           ay[idxs[j]] += val;
2000a3df083aSStefano Zampini         }
2001a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
2002a3df083aSStefano Zampini       } else {
2003a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2004a3df083aSStefano Zampini           ay[idxs[j]] += val;
2005a3df083aSStefano Zampini         }
2006a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
2007a3df083aSStefano Zampini       }
2008a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
2009a3df083aSStefano Zampini     }
2010a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
2011a3df083aSStefano Zampini   }
2012a3df083aSStefano Zampini   PetscFunctionReturn(0);
2013a3df083aSStefano Zampini }
2014a3df083aSStefano Zampini 
2015a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
2016a3df083aSStefano Zampini {
2017a3df083aSStefano Zampini   PetscErrorCode ierr;
2018a3df083aSStefano Zampini 
2019a3df083aSStefano Zampini   PetscFunctionBegin;
2020a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
2021a3df083aSStefano Zampini   PetscFunctionReturn(0);
2022a3df083aSStefano Zampini }
2023a3df083aSStefano Zampini 
2024a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
2025a3df083aSStefano Zampini {
2026a3df083aSStefano Zampini   PetscErrorCode ierr;
2027a3df083aSStefano Zampini 
2028a3df083aSStefano Zampini   PetscFunctionBegin;
2029a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
2030a3df083aSStefano Zampini   PetscFunctionReturn(0);
2031a3df083aSStefano Zampini }
2032a3df083aSStefano Zampini 
2033a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
2034a3df083aSStefano Zampini {
2035a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
2036a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
2037a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
2038a3df083aSStefano Zampini   PetscErrorCode          ierr;
2039a3df083aSStefano Zampini 
2040a3df083aSStefano Zampini   PetscFunctionBegin;
2041a3df083aSStefano Zampini   if (!restore) {
20421dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2043a3df083aSStefano Zampini     PetscScalar        *work;
2044b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2045a3df083aSStefano Zampini 
20469a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20479a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
2048a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
2049a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
2050a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2051a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
2052a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
2053a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
2054a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2055a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2056a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2057a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2058a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2059a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2060059032f7SStefano Zampini     if (reuse) {
2061a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20621dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2063059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2064059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2065059032f7SStefano Zampini       PetscInt               i;
2066059032f7SStefano Zampini 
2067059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2068059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2069059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2070059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2071059032f7SStefano Zampini       }
2072059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20731dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2074059032f7SStefano Zampini     }
2075a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2076a3df083aSStefano Zampini     ctx->work = work;
2077a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2078a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2079a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2080a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2081a3df083aSStefano Zampini 
2082a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2083a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2084a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2085a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2086a3df083aSStefano Zampini   } else {
20871dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20881dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20891dd7afcfSStefano Zampini     }
2090a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2091a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2092a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20931dd7afcfSStefano Zampini     ctx->A = NULL;
20941dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20951dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20961dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20971dd7afcfSStefano Zampini     if (ctx->free) {
2098059032f7SStefano Zampini       PetscInt i;
20991dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2100059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2101059032f7SStefano Zampini       }
2102059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2103059032f7SStefano Zampini     }
2104a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2105a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2106a3df083aSStefano Zampini   }
2107a3df083aSStefano Zampini   PetscFunctionReturn(0);
2108a3df083aSStefano Zampini }
2109a3df083aSStefano Zampini 
2110a3df083aSStefano Zampini /* used just in bddc debug mode */
2111a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2112a3df083aSStefano Zampini {
2113a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2114a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2115a3df083aSStefano Zampini   Mat            An;
2116a3df083aSStefano Zampini   PetscErrorCode ierr;
2117a3df083aSStefano Zampini 
2118a3df083aSStefano Zampini   PetscFunctionBegin;
2119a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2120a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2121a3df083aSStefano Zampini   if (is1) {
21227dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2123a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2124a3df083aSStefano Zampini   } else {
2125a3df083aSStefano Zampini     *B = An;
2126a3df083aSStefano Zampini   }
2127a3df083aSStefano Zampini   PetscFunctionReturn(0);
2128a3df083aSStefano Zampini }
2129a3df083aSStefano Zampini 
21301cf9b237SStefano Zampini /* TODO: add reuse flag */
21311cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
21321cf9b237SStefano Zampini {
21331cf9b237SStefano Zampini   Mat            Bt;
21341cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
21351cf9b237SStefano Zampini   const PetscInt *ii,*ij;
21361cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
21371cf9b237SStefano Zampini   PetscBool      flg_row;
21381cf9b237SStefano Zampini   PetscErrorCode ierr;
21391cf9b237SStefano Zampini 
21401cf9b237SStefano Zampini   PetscFunctionBegin;
21411cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
21421cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21431cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
21441cf9b237SStefano Zampini   nnz = n;
21451cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21461cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21471cf9b237SStefano Zampini   }
21481cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
21491cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
21501cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
21511cf9b237SStefano Zampini   nnz = 0;
21521cf9b237SStefano Zampini   bii[0] = 0;
21531cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21541cf9b237SStefano Zampini     PetscInt j;
21551cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21561cf9b237SStefano Zampini       PetscScalar entry = a[j];
21573272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21581cf9b237SStefano Zampini         bij[nnz] = ij[j];
21591cf9b237SStefano Zampini         bdata[nnz] = entry;
21601cf9b237SStefano Zampini         nnz++;
21611cf9b237SStefano Zampini       }
21621cf9b237SStefano Zampini     }
21631cf9b237SStefano Zampini     bii[i+1] = nnz;
21641cf9b237SStefano Zampini   }
21651cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21661cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21671cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21681cf9b237SStefano Zampini   {
21691cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21701cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21711cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21721cf9b237SStefano Zampini   }
21733272d46bSStefano Zampini   if (*B == A) {
21743272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21753272d46bSStefano Zampini   }
21761cf9b237SStefano Zampini   *B = Bt;
21771cf9b237SStefano Zampini   PetscFunctionReturn(0);
21781cf9b237SStefano Zampini }
21791cf9b237SStefano Zampini 
21808361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21814f1b2e48SStefano Zampini {
2182c80a6c00SStefano Zampini   Mat                    B = NULL;
2183c80a6c00SStefano Zampini   DM                     dm;
21844f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21854f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21864f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2187c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21884f1b2e48SStefano Zampini   PetscInt               i,n;
21894f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2190c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21914f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21924f1b2e48SStefano Zampini 
21934f1b2e48SStefano Zampini   PetscFunctionBegin;
2194a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2195a2eca866SStefano Zampini   if (cc) *cc = NULL;
2196a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2197c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2198c80a6c00SStefano Zampini   ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
21994f819b78SStefano Zampini   if (!dm) {
22004f819b78SStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2201c80a6c00SStefano Zampini   }
2202c80a6c00SStefano Zampini   if (dm) {
2203c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2204c80a6c00SStefano Zampini   }
22058361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
22068361f951SStefano Zampini 
2207c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2208c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2209c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2210c80a6c00SStefano Zampini     IS             cellNumbering;
2211c80a6c00SStefano Zampini     const PetscInt *cellNum;
2212c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2213c80a6c00SStefano Zampini     PetscSection   section;
2214c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2215c80a6c00SStefano Zampini     PetscSF        sfPoint;
2216c80a6c00SStefano Zampini     PetscErrorCode ierr;
2217c80a6c00SStefano Zampini 
2218c80a6c00SStefano Zampini     PetscFunctionBegin;
2219c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2220c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2221c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2222c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2223c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2224c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2225c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2226c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2227b0441da4SMatthew G. Knepley     ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr);
2228b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
2229956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2230c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2231c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2232c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2233c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2234c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2235c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2236c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2237c80a6c00SStefano Zampini         const PetscInt point = adj[a];
22385cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2239c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2240c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2241c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2242c80a6c00SStefano Zampini           *pBuf = point;
2243c80a6c00SStefano Zampini         }
2244c80a6c00SStefano Zampini       }
2245c80a6c00SStefano Zampini       n++;
2246c80a6c00SStefano Zampini     }
2247b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr);
2248c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2249c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2250c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2251c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2252c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2253c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2254c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2255c80a6c00SStefano Zampini     }
2256c80a6c00SStefano Zampini     xadj[n] = size;
2257c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2258c80a6c00SStefano Zampini     /* Clean up */
2259c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2260c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2261c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2262c80a6c00SStefano Zampini     graph->xadj = xadj;
2263c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2264c80a6c00SStefano Zampini   } else {
2265c80a6c00SStefano Zampini     Mat       A;
22668361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2267c80a6c00SStefano Zampini 
2268c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
226963c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2270a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
227163c961adSStefano Zampini       PetscFunctionReturn(0);
227263c961adSStefano Zampini     }
22734f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22744f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22751cf9b237SStefano Zampini       PetscBool isseqdense;
22761cf9b237SStefano Zampini 
22771cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22781cf9b237SStefano Zampini       if (!isseqdense) {
22794f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22801cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22811cf9b237SStefano Zampini         PetscScalar *array;
22821cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22831cf9b237SStefano Zampini 
22841cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22851cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22861cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22871cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22881cf9b237SStefano Zampini           PetscInt j;
22891cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22901cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22911cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22921cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22931cf9b237SStefano Zampini           }
22941cf9b237SStefano Zampini         }
22951cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22969d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22971cf9b237SStefano Zampini       }
22984f1b2e48SStefano Zampini     } else {
2299c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
23004f1b2e48SStefano Zampini       B = A;
23014f1b2e48SStefano Zampini     }
23024f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23034f1b2e48SStefano Zampini 
23044f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
23054f1b2e48SStefano Zampini     if (filter) {
23064f1b2e48SStefano Zampini       PetscScalar *data;
23074f1b2e48SStefano Zampini       PetscInt    j,cum;
23084f1b2e48SStefano Zampini 
23094f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
23104f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
23114f1b2e48SStefano Zampini       cum = 0;
23124f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
23134f1b2e48SStefano Zampini         PetscInt t;
23144f1b2e48SStefano Zampini 
23154f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
23164f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
23174f1b2e48SStefano Zampini             continue;
23184f1b2e48SStefano Zampini           }
23194f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
23204f1b2e48SStefano Zampini         }
23214f1b2e48SStefano Zampini         t = xadj_filtered[i];
23224f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
23234f1b2e48SStefano Zampini         cum += t;
23244f1b2e48SStefano Zampini       }
23254f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
23264f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
23274f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
23284f1b2e48SStefano Zampini     } else {
23294f1b2e48SStefano Zampini       graph->xadj = xadj;
23304f1b2e48SStefano Zampini       graph->adjncy = adjncy;
23314f1b2e48SStefano Zampini     }
2332c80a6c00SStefano Zampini   }
2333c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2334c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2335c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2336c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2337c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2338c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
23394f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
23404f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2341c80a6c00SStefano Zampini 
23424f1b2e48SStefano Zampini   /* partial clean up */
23434f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2344c80a6c00SStefano Zampini   if (B) {
2345c80a6c00SStefano Zampini     PetscBool flg_row;
23464f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23474f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
23484f1b2e48SStefano Zampini   }
2349c80a6c00SStefano Zampini   if (isplex) {
2350c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2351c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2352c80a6c00SStefano Zampini   }
23534f1b2e48SStefano Zampini 
23544f1b2e48SStefano Zampini   /* get back data */
2355c80a6c00SStefano Zampini   if (isplex) {
2356c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2357c80a6c00SStefano Zampini     if (cc || primalv) {
2358c80a6c00SStefano Zampini       Mat          A;
2359c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2360c80a6c00SStefano Zampini       PetscSection subSection;
2361c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2362c80a6c00SStefano Zampini 
2363c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2364c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2365c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2366c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2367c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2368c80a6c00SStefano Zampini 
2369c80a6c00SStefano Zampini       cids[0] = 0;
2370c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2371c80a6c00SStefano Zampini         PetscInt j;
2372c80a6c00SStefano Zampini 
2373c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2374c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2375c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2376c80a6c00SStefano Zampini 
2377c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2378c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
237920c3699dSStefano Zampini             PetscInt s, pp, p = closure[k], off, dof, cdof;
2380c80a6c00SStefano Zampini 
2381c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection,p,&cdof);CHKERRQ(ierr);
2382c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2383c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2384c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2385c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2386c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2387c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2388c80a6c00SStefano Zampini               } else { /* cross-vertex */
2389c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2390c80a6c00SStefano Zampini               }
2391c80a6c00SStefano Zampini             }
239220c3699dSStefano Zampini             ierr = DMPlexGetTreeParent(dm,p,&pp,NULL);CHKERRQ(ierr);
239320c3699dSStefano Zampini             if (pp != p) {
239420c3699dSStefano Zampini               ierr = PetscSectionGetConstraintDof(subSection,pp,&cdof);CHKERRQ(ierr);
239520c3699dSStefano Zampini               ierr = PetscSectionGetOffset(subSection,pp,&off);CHKERRQ(ierr);
239620c3699dSStefano Zampini               ierr = PetscSectionGetDof(subSection,pp,&dof);CHKERRQ(ierr);
239720c3699dSStefano Zampini               for (s = 0; s < dof-cdof; s++) {
239820c3699dSStefano Zampini                 if (PetscBTLookupSet(btvt,off+s)) continue;
239920c3699dSStefano Zampini                 if (!PetscBTLookup(btv,off+s)) {
240020c3699dSStefano Zampini                   ids[cum++] = off+s;
240120c3699dSStefano Zampini                 } else { /* cross-vertex */
240220c3699dSStefano Zampini                   pids[cump++] = off+s;
240320c3699dSStefano Zampini                 }
240420c3699dSStefano Zampini               }
240520c3699dSStefano Zampini             }
2406c80a6c00SStefano Zampini           }
2407c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2408c80a6c00SStefano Zampini         }
2409c80a6c00SStefano Zampini         cids[i+1] = cum;
2410c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2411c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2412c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2413c80a6c00SStefano Zampini         }
2414c80a6c00SStefano Zampini       }
2415c80a6c00SStefano Zampini       if (cc) {
2416c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2417c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2418c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2419c80a6c00SStefano Zampini         }
2420c80a6c00SStefano Zampini         *cc = cc_n;
2421c80a6c00SStefano Zampini       }
2422c80a6c00SStefano Zampini       if (primalv) {
2423c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2424c80a6c00SStefano Zampini       }
2425c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2426c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2427c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2428c80a6c00SStefano Zampini     }
2429c80a6c00SStefano Zampini   } else {
24301cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
24311cf9b237SStefano Zampini     if (cc) {
24324f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
24334f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
24344f1b2e48SStefano 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);
24354f1b2e48SStefano Zampini       }
24364f1b2e48SStefano Zampini       *cc = cc_n;
24371cf9b237SStefano Zampini     }
2438c80a6c00SStefano Zampini   }
24394f1b2e48SStefano Zampini   /* clean up graph */
24404f1b2e48SStefano Zampini   graph->xadj = 0;
24414f1b2e48SStefano Zampini   graph->adjncy = 0;
24424f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
24434f1b2e48SStefano Zampini   PetscFunctionReturn(0);
24444f1b2e48SStefano Zampini }
24454f1b2e48SStefano Zampini 
24465408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
24475408967cSStefano Zampini {
24485408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24495408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2450dee84bffSStefano Zampini   IS             dirIS = NULL;
24514f1b2e48SStefano Zampini   PetscInt       i;
24525408967cSStefano Zampini   PetscErrorCode ierr;
24535408967cSStefano Zampini 
24545408967cSStefano Zampini   PetscFunctionBegin;
2455dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
24565408967cSStefano Zampini   if (zerodiag) {
24575408967cSStefano Zampini     Mat            A;
24585408967cSStefano Zampini     Vec            vec3_N;
24595408967cSStefano Zampini     PetscScalar    *vals;
24605408967cSStefano Zampini     const PetscInt *idxs;
2461d12d3064SStefano Zampini     PetscInt       nz,*count;
24625408967cSStefano Zampini 
24635408967cSStefano Zampini     /* p0 */
24645408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
24655408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24665408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24675408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24684f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24695408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24705408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24715408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24725408967cSStefano Zampini     /* v_I */
24735408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24745408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24755408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24765408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24775408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24785408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24795408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24805408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24815408967cSStefano Zampini     if (dirIS) {
24825408967cSStefano Zampini       PetscInt n;
24835408967cSStefano Zampini 
24845408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24855408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24865408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24875408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24885408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24895408967cSStefano Zampini     }
24905408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24915408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24925408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24935408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2494669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24955408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24965408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24979a962809SStefano 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]));
24985408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24995408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2500d12d3064SStefano Zampini 
2501d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2502d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2503d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2504d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2505d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2506d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25076080607fSStefano 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]);
2508d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2509d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
25105408967cSStefano Zampini   }
2511dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
25125408967cSStefano Zampini 
25135408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
25145408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
25154f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
25165408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
25174f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
25185408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2519f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2520f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
25216080607fSStefano 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);
2522f2a566d8SStefano Zampini   }
25235408967cSStefano Zampini   PetscFunctionReturn(0);
25245408967cSStefano Zampini }
25255408967cSStefano Zampini 
25263b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2527339f8db1SStefano Zampini {
2528339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
25293b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
25303b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
25314edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
25324edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2533339f8db1SStefano Zampini   PetscErrorCode ierr;
2534339f8db1SStefano Zampini 
2535339f8db1SStefano Zampini   PetscFunctionBegin;
25363b03f7bbSStefano Zampini   if (reuse) goto project_b0;
25379f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
25389f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2539a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2540a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2541a3df083aSStefano Zampini   }
2542a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
25433b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
25443b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
25453b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
25463b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
25474f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
25484f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
25491ae86dd6SStefano Zampini      since the local Schur complements are already SPD
25504f1b2e48SStefano Zampini   */
255140fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
25527fbe2174Sstefano_zampini     IS        iP = NULL;
25533b03f7bbSStefano Zampini     PetscInt  p,*pp;
25543b03f7bbSStefano Zampini     PetscBool flg;
25554f1b2e48SStefano Zampini 
25563b03f7bbSStefano Zampini     ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp);CHKERRQ(ierr);
25573b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
255828b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
25593b03f7bbSStefano Zampini     ierr = PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg);CHKERRQ(ierr);
256028b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
25613b03f7bbSStefano Zampini     if (!flg) {
25623b03f7bbSStefano Zampini       n = 1;
25633b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25643b03f7bbSStefano Zampini     }
25653b03f7bbSStefano Zampini 
25663b03f7bbSStefano Zampini     bsp = 0;
25673b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25683b03f7bbSStefano Zampini       PetscInt bs;
25693b03f7bbSStefano Zampini 
25703b03f7bbSStefano 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]);
25713b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25723b03f7bbSStefano Zampini       bsp += bs;
25733b03f7bbSStefano Zampini     }
25743b03f7bbSStefano Zampini     ierr = PetscMalloc1(bsp,&bzerodiag);CHKERRQ(ierr);
25753b03f7bbSStefano Zampini     bsp  = 0;
25763b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25773b03f7bbSStefano Zampini       const PetscInt *idxs;
25783b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25793b03f7bbSStefano Zampini 
25803b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25813b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl);CHKERRQ(ierr);
25823b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25833b03f7bbSStefano Zampini       ierr = PetscMalloc1(npl/bs,&bidxs);CHKERRQ(ierr);
25843b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25853b03f7bbSStefano Zampini         PetscInt i;
25863b03f7bbSStefano Zampini 
25873b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25883b03f7bbSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]);CHKERRQ(ierr);
25893b03f7bbSStefano Zampini         bsp++;
25903b03f7bbSStefano Zampini       }
25913b03f7bbSStefano Zampini       ierr = PetscFree(bidxs);CHKERRQ(ierr);
25923b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25933b03f7bbSStefano Zampini     }
25943b03f7bbSStefano Zampini     ierr = ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures);CHKERRQ(ierr);
25953b03f7bbSStefano Zampini 
25967fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25977fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
25987fbe2174Sstefano_zampini     if (iP) {
25997fbe2174Sstefano_zampini       IS newpressures;
26007fbe2174Sstefano_zampini 
26017fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
26027fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
26037fbe2174Sstefano_zampini       pressures = newpressures;
26047fbe2174Sstefano_zampini     }
260540fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
260640fa8d13SStefano Zampini     if (!sorted) {
260740fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
260840fa8d13SStefano Zampini     }
26093b03f7bbSStefano Zampini     ierr = PetscFree(pp);CHKERRQ(ierr);
261040fa8d13SStefano Zampini   }
26113b03f7bbSStefano Zampini 
261297d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
261397d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
261427b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
261597d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2616339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2617339f8db1SStefano Zampini   if (!sorted) {
2618339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2619339f8db1SStefano Zampini   }
26204edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26214edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2622339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26234f1b2e48SStefano Zampini   if (!nz) {
26244f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
26254f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
262640fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
262740fa8d13SStefano Zampini   }
26284f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
26293b03f7bbSStefano Zampini 
26304f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
26314f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
26323b03f7bbSStefano Zampini   benign_n         = 0;
26331f4df5f7SStefano Zampini   n_interior_dofs  = 0;
26341f4df5f7SStefano Zampini   interior_dofs    = NULL;
26354edc6404Sstefano_zampini   nneu             = 0;
26364edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
26374edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
26384edc6404Sstefano_zampini   }
26393369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
26404edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
26411f4df5f7SStefano Zampini     PetscInt n,i,j;
26421f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
26431f4df5f7SStefano Zampini     PetscInt *iwork;
26441f4df5f7SStefano Zampini 
26451f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
26461f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26471f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
26481f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
264990648384SStefano Zampini     for (i=1;i<n_neigh;i++)
26501f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
26511f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
26521f4df5f7SStefano Zampini     for (i=0;i<n;i++)
26531f4df5f7SStefano Zampini       if (!iwork[i])
26541f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
26551f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
26561f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26571f4df5f7SStefano Zampini   }
26584f1b2e48SStefano Zampini   if (has_null_pressures) {
26594f1b2e48SStefano Zampini     IS             *subs;
26604edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26611f4df5f7SStefano Zampini     const PetscInt *idxs;
26621f4df5f7SStefano Zampini     PetscScalar    *array;
26631f4df5f7SStefano Zampini     Vec            *work;
26641f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
26654f1b2e48SStefano Zampini 
26664f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26674f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26681f4df5f7SStefano 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) */
26694edc6404Sstefano_zampini     if (checkb) {
26701f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
26711f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
26721f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
26731f4df5f7SStefano Zampini       /* work[0] = 1_p */
26741f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
26751f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
26761f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26771f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
26781f4df5f7SStefano Zampini       /* work[0] = 1_v */
26791f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
26801f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
26811f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26821f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
26831f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
26841f4df5f7SStefano Zampini     }
26853b03f7bbSStefano Zampini 
26863b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26873b03f7bbSStefano Zampini       IS       *is;
26883b03f7bbSStefano Zampini       PetscInt b,totb;
26893b03f7bbSStefano Zampini 
26903b03f7bbSStefano Zampini       totb  = bsp;
26913b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26923b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
26933b03f7bbSStefano Zampini       ierr  = PetscCalloc1(nsubs*totb,&zerodiag_subs);CHKERRQ(ierr);
26943b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
26954f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
26964f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
26974f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
26984f1b2e48SStefano Zampini           PetscInt               nl;
26994f1b2e48SStefano Zampini 
27003b03f7bbSStefano Zampini           if (subs) {
27014f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
27023b03f7bbSStefano Zampini           } else {
27033b03f7bbSStefano Zampini             IS tis;
27043b03f7bbSStefano Zampini 
27053b03f7bbSStefano Zampini             ierr = MatGetLocalSize(pcbddc->local_mat,&nl,NULL);CHKERRQ(ierr);
27063b03f7bbSStefano Zampini             ierr = ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis);CHKERRQ(ierr);
27073b03f7bbSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(tis,&l2g);CHKERRQ(ierr);
27083b03f7bbSStefano Zampini             ierr = ISDestroy(&tis);CHKERRQ(ierr);
27093b03f7bbSStefano Zampini           }
27103b03f7bbSStefano Zampini           ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs);CHKERRQ(ierr);
27114f1b2e48SStefano Zampini           ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
27124f1b2e48SStefano Zampini           if (nl) {
27134f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
27144f1b2e48SStefano Zampini 
27154edc6404Sstefano_zampini             if (checkb) {
27161f4df5f7SStefano Zampini               ierr = VecSet(matis->x,0);CHKERRQ(ierr);
27171f4df5f7SStefano Zampini               ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
27181f4df5f7SStefano Zampini               ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
27191f4df5f7SStefano Zampini               ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27201f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
27211f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27221f4df5f7SStefano Zampini               ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
27231f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
27241f4df5f7SStefano Zampini               ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
27251f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
27261f4df5f7SStefano Zampini               ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
27271f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
27281f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27291f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
27301f4df5f7SStefano Zampini                   break;
27311f4df5f7SStefano Zampini                 }
27321f4df5f7SStefano Zampini               }
27331f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
27341f4df5f7SStefano Zampini             }
27356632bad2Sstefano_zampini             if (valid && nneu) {
27366632bad2Sstefano_zampini               const PetscInt *idxs;
27371f4df5f7SStefano Zampini               PetscInt       nzb;
27381f4df5f7SStefano Zampini 
27396632bad2Sstefano_zampini               ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27406632bad2Sstefano_zampini               ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
27416632bad2Sstefano_zampini               ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27421f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
27431f4df5f7SStefano Zampini             }
27441f4df5f7SStefano Zampini             if (valid && pressures) {
27453b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
27463b03f7bbSStefano Zampini               PetscInt i1,i2;
27473b03f7bbSStefano Zampini 
27484f1b2e48SStefano Zampini               ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
27493b03f7bbSStefano Zampini               ierr = ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp);CHKERRQ(ierr);
27503b03f7bbSStefano Zampini               ierr = ISGetLocalSize(tmp,&i1);CHKERRQ(ierr);
27513b03f7bbSStefano Zampini               ierr = ISGetLocalSize(t_zerodiag_subs,&i2);CHKERRQ(ierr);
27523b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
27534f1b2e48SStefano Zampini               ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
27543b03f7bbSStefano Zampini               ierr = ISDestroy(&tmp);CHKERRQ(ierr);
27554f1b2e48SStefano Zampini             }
27564f1b2e48SStefano Zampini             if (valid) {
27573b03f7bbSStefano Zampini               ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]);CHKERRQ(ierr);
27583b03f7bbSStefano Zampini               benign_n++;
27593b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27604f1b2e48SStefano Zampini           }
27614f1b2e48SStefano Zampini           ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
27624f1b2e48SStefano Zampini           ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
27634f1b2e48SStefano Zampini         }
27643b03f7bbSStefano Zampini       }
27654f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27664f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27671f4df5f7SStefano Zampini 
27686632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27691f4df5f7SStefano Zampini       if (valid && pressures) {
27704f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
27714f1b2e48SStefano Zampini       }
27724edc6404Sstefano_zampini       if (valid && checkb) {
27731f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
27741f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
27751f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27761f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27771f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27781f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27791f4df5f7SStefano Zampini             break;
27801f4df5f7SStefano Zampini           }
27811f4df5f7SStefano Zampini         }
27821f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27831f4df5f7SStefano Zampini       }
27844f1b2e48SStefano Zampini       if (valid) {
27853b03f7bbSStefano Zampini         benign_n = 1;
27863b03f7bbSStefano Zampini         ierr = PetscMalloc1(benign_n,&zerodiag_subs);CHKERRQ(ierr);
27874f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
27884f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27894f1b2e48SStefano Zampini       }
27904f1b2e48SStefano Zampini     }
27914edc6404Sstefano_zampini     if (checkb) {
27921f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
27934f1b2e48SStefano Zampini     }
27941f4df5f7SStefano Zampini   }
27951f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
27964f1b2e48SStefano Zampini 
27973b03f7bbSStefano Zampini   if (!benign_n) {
2798b9b0e38cSStefano Zampini     PetscInt n;
2799b9b0e38cSStefano Zampini 
28004f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28014f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2802b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
280376a58201SStefano Zampini     if (n) have_null = PETSC_FALSE;
2804b9b0e38cSStefano Zampini   }
28054f1b2e48SStefano Zampini 
28064f1b2e48SStefano Zampini   /* final check for null pressures */
28074f1b2e48SStefano Zampini   if (zerodiag && pressures) {
28083b03f7bbSStefano Zampini     ierr = ISEqual(pressures,zerodiag,&have_null);CHKERRQ(ierr);
28094f1b2e48SStefano Zampini   }
28104f1b2e48SStefano Zampini 
28114f1b2e48SStefano Zampini   if (recompute_zerodiag) {
28124f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28133b03f7bbSStefano Zampini     if (benign_n == 1) {
28144f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
28154f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
28164f1b2e48SStefano Zampini     } else {
28174f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
28184f1b2e48SStefano Zampini 
28194f1b2e48SStefano Zampini       nzn = 0;
28203b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28214f1b2e48SStefano Zampini         PetscInt ns;
28224f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28234f1b2e48SStefano Zampini         nzn += ns;
28244f1b2e48SStefano Zampini       }
28254f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
28264f1b2e48SStefano Zampini       nzn = 0;
28273b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28284f1b2e48SStefano Zampini         PetscInt ns,*idxs;
28294f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28304f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2831*580bdb30SBarry Smith         ierr = PetscArraycpy(new_idxs+nzn,idxs,ns);CHKERRQ(ierr);
28324f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
28334f1b2e48SStefano Zampini         nzn += ns;
28344f1b2e48SStefano Zampini       }
28354f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
28364f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
28374f1b2e48SStefano Zampini     }
28384f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
28394f1b2e48SStefano Zampini   }
28404f1b2e48SStefano Zampini 
28413b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
28423b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
28433b03f7bbSStefano Zampini 
2844669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2845a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2846a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2847a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2848a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2849a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2850a198735bSStefano Zampini 
28511f4df5f7SStefano Zampini     if (pressures) {
28521f4df5f7SStefano Zampini       isused = pressures;
28531f4df5f7SStefano Zampini     } else {
28544edc6404Sstefano_zampini       isused = zerodiag_save;
28551f4df5f7SStefano Zampini     }
2856a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2857669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
28581ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
28591ae86dd6SStefano 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");
2860a198735bSStefano Zampini     n_isused = 0;
2861a198735bSStefano Zampini     if (isused) {
2862a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2863a198735bSStefano Zampini     }
2864a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2865a198735bSStefano Zampini     st = st-n_isused;
28661ae86dd6SStefano Zampini     if (n) {
2867a198735bSStefano Zampini       const PetscInt *gidxs;
2868a198735bSStefano Zampini 
28697dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2870a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2871a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2872a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2873a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2874a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
28751ae86dd6SStefano Zampini     } else {
2876a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2877a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2878a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2879a198735bSStefano Zampini     }
2880a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2881a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2882a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2883a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2884a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2885a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2886a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2887a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2888a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2889a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2890a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2891a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2892a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2893a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
28941ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28951ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28961ae86dd6SStefano Zampini   }
28974edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
28983b03f7bbSStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
28993b03f7bbSStefano Zampini   if (bzerodiag) {
29003b03f7bbSStefano Zampini     PetscInt i;
2901b3afcdbeSStefano Zampini 
29023b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
29033b03f7bbSStefano Zampini       ierr = ISDestroy(&bzerodiag[i]);CHKERRQ(ierr);
29043b03f7bbSStefano Zampini     }
29053b03f7bbSStefano Zampini     ierr = PetscFree(bzerodiag);CHKERRQ(ierr);
29063b03f7bbSStefano Zampini   }
29073b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
29083b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
29093b03f7bbSStefano Zampini 
29103b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
29113b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
29123b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
29133b03f7bbSStefano Zampini 
29143b03f7bbSStefano Zampini project_b0:
2915aa0d93e9SStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2916b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
29173b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
29184f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
29194f1b2e48SStefano Zampini 
2920339f8db1SStefano Zampini     /* local change of basis for pressures */
2921339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
292297d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2923339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2924339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2925339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
2926aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
29274f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2928aa0d93e9SStefano Zampini       const PetscInt *idxs;
29294f1b2e48SStefano Zampini       PetscInt       nzs,j;
29304f1b2e48SStefano Zampini 
29313b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs);CHKERRQ(ierr);
29323b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29334f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
29344f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
29353b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29364f1b2e48SStefano Zampini     }
2937339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2938e1b21442SStefano Zampini     ierr = MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2939339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2940aa0d93e9SStefano Zampini     /* set identity by default */
2941aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
2942aa0d93e9SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES);CHKERRQ(ierr);
2943339f8db1SStefano Zampini     }
29449f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
29454f1b2e48SStefano 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);
2946339f8db1SStefano Zampini     /* set change on pressures */
29474f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
29484f1b2e48SStefano Zampini       PetscScalar    *array;
2949aa0d93e9SStefano Zampini       const PetscInt *idxs;
29504f1b2e48SStefano Zampini       PetscInt       nzs;
29514f1b2e48SStefano Zampini 
29523b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs);CHKERRQ(ierr);
29533b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
29544f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2955339f8db1SStefano Zampini         PetscScalar vals[2];
2956339f8db1SStefano Zampini         PetscInt    cols[2];
2957339f8db1SStefano Zampini 
2958339f8db1SStefano Zampini         cols[0] = idxs[i];
29594f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2960339f8db1SStefano Zampini         vals[0] = 1.;
2961b0f5fe93SStefano Zampini         vals[1] = 1.;
29624f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2963339f8db1SStefano Zampini       }
29644f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
29654f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29664f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29674f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
29684f1b2e48SStefano Zampini       /* store local idxs for p0 */
29694f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29703b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2971339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
29724f1b2e48SStefano Zampini     }
2973339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2974339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29753b03f7bbSStefano Zampini 
2976a3df083aSStefano Zampini     /* project if needed */
2977a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29781dd7afcfSStefano Zampini       Mat M;
29791dd7afcfSStefano Zampini 
29801dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2981339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
29821dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
29831dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2984a3df083aSStefano Zampini     }
29854f1b2e48SStefano Zampini     /* store global idxs for p0 */
29864f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2987339f8db1SStefano Zampini   }
2988339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2989339f8db1SStefano Zampini   PetscFunctionReturn(0);
2990339f8db1SStefano Zampini }
2991339f8db1SStefano Zampini 
2992015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2993efc2fbd9SStefano Zampini {
2994efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2995de9d7bd0SStefano Zampini   PetscScalar    *array;
2996efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2997efc2fbd9SStefano Zampini 
2998efc2fbd9SStefano Zampini   PetscFunctionBegin;
2999efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
3000efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
30014f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
3002efc2fbd9SStefano Zampini   }
3003de9d7bd0SStefano Zampini   if (get) {
3004efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
30054f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
30064f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
3007efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
3008de9d7bd0SStefano Zampini   } else {
3009de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
3010de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
3011de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
3012de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
3013efc2fbd9SStefano Zampini   }
3014efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
3015efc2fbd9SStefano Zampini }
3016efc2fbd9SStefano Zampini 
3017c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
3018c263805aSStefano Zampini {
3019c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3020c263805aSStefano Zampini   PetscErrorCode ierr;
3021c263805aSStefano Zampini 
3022c263805aSStefano Zampini   PetscFunctionBegin;
3023c263805aSStefano Zampini   /* TODO: add error checking
3024c263805aSStefano Zampini     - avoid nested pop (or push) calls.
3025c263805aSStefano Zampini     - cannot push before pop.
30261c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
3027c263805aSStefano Zampini   */
30284f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3029efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
3030efc2fbd9SStefano Zampini   }
3031c263805aSStefano Zampini   if (pop) {
3032a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30334f1b2e48SStefano Zampini       IS       is_p0;
30344f1b2e48SStefano Zampini       MatReuse reuse;
3035c263805aSStefano Zampini 
3036c263805aSStefano Zampini       /* extract B_0 */
30374f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
30384f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
30394f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
30404f1b2e48SStefano Zampini       }
30414f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
30427dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
3043c263805aSStefano Zampini       /* remove rows and cols from local problem */
3044c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
304597d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
30464f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
30474f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
3048a3df083aSStefano Zampini     } else {
3049a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
3050a3df083aSStefano Zampini       PetscScalar *vals;
3051a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
3052a3df083aSStefano Zampini 
3053a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
3054a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
3055a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30560b5adadeSStefano Zampini         PetscInt *nnz;
3057a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
3058a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
3059a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3060331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
3061331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
3062331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
3063331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3064331e053bSStefano Zampini         }
3065331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
3066e1b21442SStefano Zampini         ierr = MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3067331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
3068331e053bSStefano Zampini       }
3069a3df083aSStefano Zampini 
3070a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3071a3df083aSStefano Zampini         PetscScalar *array;
3072a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3073a3df083aSStefano Zampini 
3074a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
3075a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3076a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3077a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
3078a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
3079a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
3080a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
3081a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
3082a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
3083a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
3084a3df083aSStefano Zampini         cum = 0;
3085a3df083aSStefano Zampini         for (j=0;j<n;j++) {
308622db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3087a3df083aSStefano Zampini             vals[cum] = array[j];
3088a3df083aSStefano Zampini             idxs_ins[cum] = j;
3089a3df083aSStefano Zampini             cum++;
3090a3df083aSStefano Zampini           }
3091a3df083aSStefano Zampini         }
3092a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
3093a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
3094a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3095a3df083aSStefano Zampini       }
3096a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3097a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3098a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
3099a3df083aSStefano Zampini     }
3100c263805aSStefano Zampini   } else { /* push */
3101a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
31024f1b2e48SStefano Zampini       PetscInt i;
31034f1b2e48SStefano Zampini 
31044f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
31054f1b2e48SStefano Zampini         PetscScalar *B0_vals;
31064f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
31074f1b2e48SStefano Zampini 
31084f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31094f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31107b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31114f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
31124f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31134f1b2e48SStefano Zampini       }
3114c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3115c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31166080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3117c263805aSStefano Zampini   }
3118c263805aSStefano Zampini   PetscFunctionReturn(0);
3119c263805aSStefano Zampini }
3120c263805aSStefano Zampini 
312108122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3122b1b3d7a2SStefano Zampini {
3123b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
312408122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
312508122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
312608122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
312708122e43SStefano Zampini   PetscScalar     *work,lwork;
312808122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
312908122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3130bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
31311b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3132f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
313308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
313408122e43SStefano Zampini   PetscReal       *rwork;
313508122e43SStefano Zampini #endif
3136b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3137b1b3d7a2SStefano Zampini 
3138b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3139b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3140af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3141bd2a564bSStefano 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);
314243371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
314306a4e24aSStefano Zampini 
3144fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3145fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3146fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3147fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
31481575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3149fd14bc51SStefano Zampini   }
3150fd14bc51SStefano Zampini 
3151e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
31526080607fSStefano 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);
3153e496cd5dSStefano Zampini   }
3154e496cd5dSStefano Zampini 
315508122e43SStefano Zampini   /* max size of subsets */
315608122e43SStefano Zampini   mss = 0;
315708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
315808122e43SStefano Zampini     PetscInt subset_size;
3159862806e4SStefano Zampini 
316008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
316108122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
316208122e43SStefano Zampini   }
316308122e43SStefano Zampini 
316408122e43SStefano Zampini   /* min/max and threshold */
316508122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3166f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
316708122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3168f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3169bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3170f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3171f6f667cfSStefano Zampini   }
317208122e43SStefano Zampini 
317308122e43SStefano Zampini   /* allocate lapack workspace */
317408122e43SStefano Zampini   cum = cum2 = 0;
317508122e43SStefano Zampini   maxneigs = 0;
317608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
317708122e43SStefano Zampini     PetscInt n,subset_size;
3178f6f667cfSStefano Zampini 
317908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
318008122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31819162d606SStefano Zampini     cum += subset_size;
31829162d606SStefano Zampini     cum2 += subset_size*n;
318308122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
318408122e43SStefano Zampini   }
318508122e43SStefano Zampini   if (mss) {
3186bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
318708122e43SStefano Zampini       PetscBLASInt B_itype = 1;
318808122e43SStefano Zampini       PetscBLASInt B_N = mss;
31894c6709b3SStefano Zampini       PetscReal    zero = 0.0;
31904c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
319108122e43SStefano Zampini 
319208122e43SStefano Zampini       B_lwork = -1;
319308122e43SStefano Zampini       S = NULL;
319408122e43SStefano Zampini       St = NULL;
3195a58a30b4SStefano Zampini       eigs = NULL;
3196a58a30b4SStefano Zampini       eigv = NULL;
3197a58a30b4SStefano Zampini       B_iwork = NULL;
3198a58a30b4SStefano Zampini       B_ifail = NULL;
3199d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3200d1710679SStefano Zampini       rwork = NULL;
3201d1710679SStefano Zampini #endif
32028bec7fa6SStefano Zampini       thresh = 1.0;
320308122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
320408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
320508122e43SStefano 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));
320608122e43SStefano Zampini #else
320708122e43SStefano 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));
320808122e43SStefano Zampini #endif
320908122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
321008122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3211bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
321208122e43SStefano Zampini   } else {
321308122e43SStefano Zampini     lwork = 0;
321408122e43SStefano Zampini   }
321508122e43SStefano Zampini 
321608122e43SStefano Zampini   nv = 0;
3217d62866d3SStefano 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) */
3218d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
321908122e43SStefano Zampini   }
32204c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3221f6f667cfSStefano Zampini   if (allocated_S_St) {
3222f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3223f6f667cfSStefano Zampini   }
3224f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
322508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
322608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
322708122e43SStefano Zampini #endif
32289162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
32299162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
32309162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
323108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
32329162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
3233*580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs);CHKERRQ(ierr);
323408122e43SStefano Zampini 
323508122e43SStefano Zampini   maxneigs = 0;
323672b8c272SStefano Zampini   cum = cumarray = 0;
32379162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
32389162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3239d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
324008122e43SStefano Zampini     const PetscInt *idxs;
324108122e43SStefano Zampini 
3242d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
324308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
324408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
324508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
324608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
32479162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
32489162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
324908122e43SStefano Zampini     }
3250d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
325108122e43SStefano Zampini   }
325208122e43SStefano Zampini 
325308122e43SStefano Zampini   if (mss) { /* multilevel */
325408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
325508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
325608122e43SStefano Zampini   }
325708122e43SStefano Zampini 
3258bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3259bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
326008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
326108122e43SStefano Zampini     const PetscInt *idxs;
32629d54b7f4SStefano Zampini     PetscReal      upper,lower;
3263862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
326408122e43SStefano Zampini     PetscBLASInt   B_N;
3265aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3266bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
326708122e43SStefano Zampini 
32689d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
32699d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3270bd2a564bSStefano Zampini       lower = uthresh;
32719d54b7f4SStefano Zampini     } else {
3272bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3273bd2a564bSStefano Zampini       upper = 1./uthresh;
32749d54b7f4SStefano Zampini       lower = 0.;
32759d54b7f4SStefano Zampini     }
3276862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3277ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3278f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3279bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3280bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3281bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3282bd2a564bSStefano Zampini       Mat T;
3283bd2a564bSStefano Zampini 
3284bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3285bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3286bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3287bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3288bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3289bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3290bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3291bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3292bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3293bd2a564bSStefano Zampini             PetscInt       nz,k;
3294bd2a564bSStefano Zampini             const PetscInt *idxs;
3295bd2a564bSStefano Zampini 
3296bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3297bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3298bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3299bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3300bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3301bd2a564bSStefano Zampini             }
3302bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3303bd2a564bSStefano Zampini           }
3304bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3305bd2a564bSStefano Zampini           break;
3306bd2a564bSStefano Zampini         }
3307bd2a564bSStefano Zampini       }
3308bd2a564bSStefano Zampini     }
3309bd2a564bSStefano Zampini 
3310f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3311bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3312aff50787SStefano Zampini         PetscInt j,k;
3313*580bdb30SBarry Smith         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */
3314*580bdb30SBarry Smith           ierr = PetscArrayzero(S,subset_size*subset_size);CHKERRQ(ierr);
3315*580bdb30SBarry Smith           ierr = PetscArrayzero(St,subset_size*subset_size);CHKERRQ(ierr);
331608122e43SStefano Zampini         }
331708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3318aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3319aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3320aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3321aff50787SStefano Zampini           }
332208122e43SStefano Zampini         }
332308122e43SStefano Zampini       } else {
3324*580bdb30SBarry Smith         ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3325*580bdb30SBarry Smith         ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
332608122e43SStefano Zampini       }
33278bec7fa6SStefano Zampini     } else {
3328f6f667cfSStefano Zampini       S = Sarray + cumarray;
3329f6f667cfSStefano Zampini       St = Starray + cumarray;
33308bec7fa6SStefano Zampini     }
3331aff50787SStefano Zampini     /* see if we can save some work */
3332b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3333*580bdb30SBarry Smith       ierr = PetscArraycmp(S,St,subset_size*subset_size,&same_data);CHKERRQ(ierr);
3334aff50787SStefano Zampini     }
3335aff50787SStefano Zampini 
3336b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3337aff50787SStefano Zampini       B_neigs = 0;
3338aff50787SStefano Zampini     } else {
3339bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
334008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3341f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
33424c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
33439552c7c7SStefano Zampini         PetscInt     nmin_s;
3344bd2a564bSStefano Zampini         PetscBool    compute_range;
3345bd2a564bSStefano Zampini 
33469036ceccSStefano Zampini         B_neigs = 0;
3347bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3348bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
334908122e43SStefano Zampini 
3350fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
33519036ceccSStefano Zampini           PetscInt nc = 0;
3352d16cbb6bSStefano Zampini 
33539036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
33549036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
33559036ceccSStefano Zampini           }
33566080607fSStefano 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);
3357b7ab4a40SStefano Zampini         }
3358b7ab4a40SStefano Zampini 
335908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3360b7ab4a40SStefano Zampini         if (compute_range) {
3361d16cbb6bSStefano Zampini 
3362d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3363bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
336408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33659d54b7f4SStefano 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));
336608122e43SStefano Zampini #else
33679d54b7f4SStefano 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));
336808122e43SStefano Zampini #endif
336943371fb9SStefano Zampini             ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3370bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33719036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3372bd2a564bSStefano Zampini             PetscReal bb[2];
3373bd2a564bSStefano Zampini 
3374bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3375bd2a564bSStefano Zampini             switch (recipe) {
3376bd2a564bSStefano Zampini             case 0:
3377bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3378bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3379bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3380bd2a564bSStefano 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));
3381bd2a564bSStefano Zampini #else
3382bd2a564bSStefano 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));
3383bd2a564bSStefano Zampini #endif
338443371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3385bd2a564bSStefano Zampini               break;
3386bd2a564bSStefano Zampini             case 1:
3387bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3388bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3389bd2a564bSStefano 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));
3390bd2a564bSStefano Zampini #else
3391bd2a564bSStefano 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));
3392bd2a564bSStefano Zampini #endif
339343371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3394bd2a564bSStefano Zampini               if (!scal) {
33959036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3396bd2a564bSStefano Zampini 
3397aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3398*580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3399*580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3400bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3401bd2a564bSStefano 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));
3402bd2a564bSStefano Zampini #else
3403bd2a564bSStefano 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));
3404bd2a564bSStefano Zampini #endif
340543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3406bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3407bd2a564bSStefano Zampini               }
3408bd2a564bSStefano Zampini               break;
34099036ceccSStefano Zampini             case 2:
34109036ceccSStefano Zampini               if (scal) {
34119036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
34129036ceccSStefano Zampini                 bb[1] = 0;
34139036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34149036ceccSStefano 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));
34159036ceccSStefano Zampini #else
34169036ceccSStefano 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));
34179036ceccSStefano Zampini #endif
341843371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34199036ceccSStefano Zampini               } else {
34209036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34219036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
34229036ceccSStefano Zampini 
34239036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
34249036ceccSStefano Zampini                 if (lthresh > 0.0) {
34259036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
34269036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
34279036ceccSStefano Zampini 
34289036ceccSStefano Zampini                   import = PETSC_TRUE;
34299036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34309036ceccSStefano 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));
34319036ceccSStefano Zampini #else
34329036ceccSStefano 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));
34339036ceccSStefano Zampini #endif
343443371fb9SStefano Zampini                   ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34359036ceccSStefano Zampini                 }
34369036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
34379036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34389036ceccSStefano Zampini                 if (import) {
3439*580bdb30SBarry Smith                   ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3440*580bdb30SBarry Smith                   ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34419036ceccSStefano Zampini                 }
34429036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34439036ceccSStefano 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));
34449036ceccSStefano Zampini #else
34459036ceccSStefano 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));
34469036ceccSStefano Zampini #endif
344743371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34489036ceccSStefano Zampini                 B_neigs += B_neigs2;
34499036ceccSStefano Zampini               }
34509036ceccSStefano Zampini               break;
34519036ceccSStefano Zampini             case 3:
34529036ceccSStefano Zampini               if (scal) {
34539036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
34549036ceccSStefano Zampini               } else {
34559036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
34569036ceccSStefano Zampini               }
34579036ceccSStefano Zampini               if (!scal) {
34589036ceccSStefano Zampini                 bb[0] = uthresh;
34599036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34609036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34619036ceccSStefano 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));
34629036ceccSStefano Zampini #else
34639036ceccSStefano 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));
34649036ceccSStefano Zampini #endif
346543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34669036ceccSStefano Zampini               }
34679036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34689036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34699036ceccSStefano Zampini 
34709036ceccSStefano Zampini                 B_IL = 1;
34719036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
3472*580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3473*580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34749036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34759036ceccSStefano 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));
34769036ceccSStefano Zampini #else
34779036ceccSStefano 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));
34789036ceccSStefano Zampini #endif
347943371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34809036ceccSStefano Zampini                 B_neigs += B_neigs2;
34819036ceccSStefano Zampini               }
34829036ceccSStefano Zampini               break;
348348cebe81SStefano Zampini             case 4:
348448cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
348548cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
348648cebe81SStefano 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));
348748cebe81SStefano Zampini #else
348848cebe81SStefano 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));
348948cebe81SStefano Zampini #endif
349043371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
349148cebe81SStefano Zampini               {
349248cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
349348cebe81SStefano Zampini 
349448cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
3495*580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3496*580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
349748cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
349848cebe81SStefano 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));
349948cebe81SStefano Zampini #else
350048cebe81SStefano 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));
350148cebe81SStefano Zampini #endif
350243371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
350348cebe81SStefano Zampini                 B_neigs += B_neigs2;
350448cebe81SStefano Zampini               }
350548cebe81SStefano Zampini               break;
350680db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
350780db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
350880db8efeSStefano 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));
350980db8efeSStefano Zampini #else
351080db8efeSStefano 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));
351180db8efeSStefano Zampini #endif
351243371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
351380db8efeSStefano Zampini               {
351480db8efeSStefano Zampini                 PetscInt e,k,ne;
351580db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
351680db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
351780db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
351880db8efeSStefano Zampini                     eigs[ne] = eigs[e];
351980db8efeSStefano Zampini                     ne++;
352080db8efeSStefano Zampini                   }
352180db8efeSStefano Zampini                 }
3522*580bdb30SBarry Smith                 ierr = PetscArraycpy(eigv,S,B_N*ne);CHKERRQ(ierr);
352380db8efeSStefano Zampini                 B_neigs = ne;
352480db8efeSStefano Zampini               }
352580db8efeSStefano Zampini               break;
3526bd2a564bSStefano Zampini             default:
3527bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3528bd2a564bSStefano Zampini               break;
3529bd2a564bSStefano Zampini             }
3530bd2a564bSStefano Zampini           }
3531bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3532d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3533d16cbb6bSStefano Zampini           B_IL = 1;
3534d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
35359d54b7f4SStefano 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));
3536d16cbb6bSStefano Zampini #else
35379d54b7f4SStefano 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));
3538d16cbb6bSStefano Zampini #endif
353943371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3540b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3541b7ab4a40SStefano Zampini           PetscInt k;
3542b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3543b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3544b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3545b7ab4a40SStefano Zampini           nmin = nmax;
3546*580bdb30SBarry Smith           ierr = PetscArrayzero(eigv,subset_size*nmax);CHKERRQ(ierr);
3547b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3548b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3549b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3550b7ab4a40SStefano Zampini           }
3551d16cbb6bSStefano Zampini         }
355208122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
355308122e43SStefano Zampini         if (B_ierr) {
35546c4ed002SBarry 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);
35556c4ed002SBarry 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);
35566c4ed002SBarry 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);
355708122e43SStefano Zampini         }
355808122e43SStefano Zampini 
355908122e43SStefano Zampini         if (B_neigs > nmax) {
3560fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35616080607fSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %D.\n",B_neigs,nmax);CHKERRQ(ierr);
3562fd14bc51SStefano Zampini           }
3563bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
356408122e43SStefano Zampini           B_neigs = nmax;
356508122e43SStefano Zampini         }
356608122e43SStefano Zampini 
35679552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35689552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35699036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
357008122e43SStefano Zampini 
35719d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3572bd2a564bSStefano Zampini             if (scal) {
3573bd2a564bSStefano Zampini               B_IU = nmin_s;
3574bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3575bd2a564bSStefano Zampini             } else {
3576f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35779d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3578bd2a564bSStefano Zampini             }
35799d54b7f4SStefano Zampini           } else {
35809d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35819d54b7f4SStefano Zampini             B_IU = nmin_s;
35829d54b7f4SStefano Zampini           }
3583fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35846080607fSStefano 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);
3585fd14bc51SStefano Zampini           }
3586bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35871ae86dd6SStefano Zampini             PetscInt j,k;
358808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35891ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35901ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35911ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
359208122e43SStefano Zampini               }
359308122e43SStefano Zampini             }
359408122e43SStefano Zampini           } else {
3595*580bdb30SBarry Smith             ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3596*580bdb30SBarry Smith             ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
359708122e43SStefano Zampini           }
359808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
359908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36009d54b7f4SStefano 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));
360108122e43SStefano Zampini #else
36029d54b7f4SStefano 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));
360308122e43SStefano Zampini #endif
360443371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
360508122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
360608122e43SStefano Zampini           B_neigs += B_neigs2;
360708122e43SStefano Zampini         }
360808122e43SStefano Zampini         if (B_ierr) {
36096c4ed002SBarry 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);
36106c4ed002SBarry 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);
36116c4ed002SBarry 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);
361208122e43SStefano Zampini         }
3613fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3614ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
361508122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
361608122e43SStefano Zampini             if (eigs[j] == 0.0) {
3617ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
361808122e43SStefano Zampini             } else {
36199d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3620ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
36219d54b7f4SStefano Zampini               } else {
36229d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
36239d54b7f4SStefano Zampini               }
3624fd14bc51SStefano Zampini             }
362508122e43SStefano Zampini           }
362608122e43SStefano Zampini         }
3627bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3628aff50787SStefano Zampini     }
36296c3e6151SStefano Zampini     /* change the basis back to the original one */
36306c3e6151SStefano Zampini     if (sub_schurs->change) {
363172b8c272SStefano Zampini       Mat change,phi,phit;
36326c3e6151SStefano Zampini 
363303dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
36346c3e6151SStefano Zampini         PetscInt ii;
36356c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
36366c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36376c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3638684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3639684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3640684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3641684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3642684229deSStefano Zampini #else
36436c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3644684229deSStefano Zampini #endif
36456c3e6151SStefano Zampini           }
36466c3e6151SStefano Zampini         }
36476c3e6151SStefano Zampini       }
364872b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
36496c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
365072b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
36516c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
36526c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
36536c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
36546c3e6151SStefano Zampini     }
36558bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36568bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36579162d606SStefano Zampini     if (B_neigs) {
3658*580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size);CHKERRQ(ierr);
3659fd14bc51SStefano Zampini 
3660fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36619552c7c7SStefano Zampini         PetscInt ii;
36629552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3663ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36649552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3665ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3666ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3667ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3668ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3669ac47001eSStefano Zampini #else
3670ac47001eSStefano 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);
3671ac47001eSStefano Zampini #endif
36729552c7c7SStefano Zampini           }
36739552c7c7SStefano Zampini         }
3674fd14bc51SStefano Zampini       }
3675*580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size);CHKERRQ(ierr);
36769162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36779162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36789162d606SStefano Zampini       cum++;
367908122e43SStefano Zampini     }
368008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
368108122e43SStefano Zampini     /* shift for next computation */
368208122e43SStefano Zampini     cumarray += subset_size*subset_size;
368308122e43SStefano Zampini   }
3684fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3685fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3686fd14bc51SStefano Zampini   }
368708122e43SStefano Zampini 
368808122e43SStefano Zampini   if (mss) {
368908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
369008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3691f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3692f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3693f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
369408122e43SStefano Zampini   }
3695f6f667cfSStefano Zampini   if (allocated_S_St) {
3696f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3697f6f667cfSStefano Zampini   }
3698f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
369908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
370008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
370108122e43SStefano Zampini #endif
370208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
37031b968477SStefano Zampini     PetscInt maxneigs_r;
3704b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
37056080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %D\n",maxneigs_r);CHKERRQ(ierr);
370608122e43SStefano Zampini   }
370743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
370808122e43SStefano Zampini   PetscFunctionReturn(0);
370908122e43SStefano Zampini }
3710b1b3d7a2SStefano Zampini 
3711c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3712c8587f34SStefano Zampini {
37138629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3714c8587f34SStefano Zampini   PetscErrorCode ierr;
3715c8587f34SStefano Zampini 
3716c8587f34SStefano Zampini   PetscFunctionBegin;
3717f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
37185e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3719c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3720c8587f34SStefano Zampini 
3721684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
37220fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3723684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3724c8587f34SStefano Zampini 
37258629588bSStefano Zampini   /*
37268629588bSStefano Zampini      Setup local correction and local part of coarse basis.
37278629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
37288629588bSStefano Zampini   */
372947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
37308629588bSStefano Zampini 
37318629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
37328629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
37338629588bSStefano Zampini 
37348629588bSStefano Zampini   /* free */
37358629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3736c8587f34SStefano Zampini   PetscFunctionReturn(0);
3737c8587f34SStefano Zampini }
3738c8587f34SStefano Zampini 
3739674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3740674ae819SStefano Zampini {
3741674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3742674ae819SStefano Zampini   PetscErrorCode ierr;
3743674ae819SStefano Zampini 
3744674ae819SStefano Zampini   PetscFunctionBegin;
3745674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
374630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3747674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3748785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3749674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3750f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3751f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3752785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
375363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
375463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3755674ae819SStefano Zampini   PetscFunctionReturn(0);
3756674ae819SStefano Zampini }
3757674ae819SStefano Zampini 
3758674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3759674ae819SStefano Zampini {
3760674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37614f1b2e48SStefano Zampini   PetscInt       i;
3762674ae819SStefano Zampini   PetscErrorCode ierr;
3763674ae819SStefano Zampini 
3764674ae819SStefano Zampini   PetscFunctionBegin;
37651e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
37661e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3767a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3768b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3769674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
377016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
37711dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3772674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3773669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3774fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
37759326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
37764f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37774f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
37784f1b2e48SStefano Zampini   }
3779e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37804f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3781e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3782c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37838af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37841c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3785674ae819SStefano Zampini   PetscFunctionReturn(0);
3786674ae819SStefano Zampini }
3787674ae819SStefano Zampini 
3788674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3789674ae819SStefano Zampini {
3790674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3791674ae819SStefano Zampini   PetscErrorCode ierr;
3792674ae819SStefano Zampini 
3793674ae819SStefano Zampini   PetscFunctionBegin;
3794674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
379558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3796ca92afb2SStefano Zampini     PetscScalar *array;
379706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
379806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
379958da7f69SStefano Zampini   }
3800674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3801674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
380215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
380315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3804674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3805674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3806674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
380706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3808674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3809674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38108ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3811674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3812674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3813674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38149326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
38159326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
38169326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3817f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3818727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
38190e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3820f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
382170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
382281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
38230369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
38241dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
38254f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
38268b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3827ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3828ca92afb2SStefano Zampini     PetscInt i;
3829ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3830ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3831ca92afb2SStefano Zampini     }
3832ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3833ca92afb2SStefano Zampini   }
38344f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3835674ae819SStefano Zampini   PetscFunctionReturn(0);
3836674ae819SStefano Zampini }
3837674ae819SStefano Zampini 
3838f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
38396bfb1811SStefano Zampini {
38406bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38416bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
38426bfb1811SStefano Zampini   VecType        impVecType;
38434f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
38446bfb1811SStefano Zampini   PetscErrorCode ierr;
38456bfb1811SStefano Zampini 
38466bfb1811SStefano Zampini   PetscFunctionBegin;
38474f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3848b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
38496bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3850e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3851e7b262bdSStefano Zampini   /* R nodes */
3852e7b262bdSStefano Zampini   old_size = -1;
3853e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3854e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3855e7b262bdSStefano Zampini   }
3856e7b262bdSStefano Zampini   if (n_R != old_size) {
3857e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3858e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38596bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
38606bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
38616bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
38626bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3863e7b262bdSStefano Zampini   }
3864e7b262bdSStefano Zampini   /* local primal dofs */
3865e7b262bdSStefano Zampini   old_size = -1;
3866e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3867e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3868e7b262bdSStefano Zampini   }
3869e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3870e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
387183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3872e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
38736bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3874e7b262bdSStefano Zampini   }
3875e7b262bdSStefano Zampini   /* local explicit constraints */
3876e7b262bdSStefano Zampini   old_size = -1;
3877e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3878e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3879e7b262bdSStefano Zampini   }
3880e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3881e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
388283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
388383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
388483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
388583b7ccabSStefano Zampini   }
38866bfb1811SStefano Zampini   PetscFunctionReturn(0);
38876bfb1811SStefano Zampini }
38886bfb1811SStefano Zampini 
388947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
389088ebb749SStefano Zampini {
389125084f0cSStefano Zampini   PetscErrorCode  ierr;
389225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
389388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
389488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3895d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
389625084f0cSStefano Zampini   /* submatrices of local problem */
389780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
389806656605SStefano Zampini   /* submatrices of local coarse problem */
389906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
390025084f0cSStefano Zampini   /* working matrices */
390106656605SStefano Zampini   Mat             C_CR;
390225084f0cSStefano Zampini   /* additional working stuff */
390306656605SStefano Zampini   PC              pc_R;
3904c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
39055cbda25cSStefano Zampini   Vec             dummy_vec;
3906c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
390725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
390806656605SStefano Zampini   PetscScalar     *work;
390906656605SStefano Zampini   PetscInt        *idx_V_B;
3910ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
391106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3912ffd830a3SStefano Zampini 
391325084f0cSStefano Zampini   /* some shortcuts to scalars */
391406656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
391588ebb749SStefano Zampini 
391688ebb749SStefano Zampini   PetscFunctionBegin;
39179a962809SStefano 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");
391843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
3919ffd830a3SStefano Zampini 
3920ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3921b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39224f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3923b371cd4fSStefano Zampini   n_B = pcis->n_B;
3924b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
392588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
392688ebb749SStefano Zampini 
392788ebb749SStefano Zampini   /* vertices in boundary numbering */
3928785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
39290e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
39306080607fSStefano Zampini   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",n_vertices,i);
393188ebb749SStefano Zampini 
393206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3933019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
393406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
393506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
393606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
393706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
393806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
393906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
394006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
394106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
394206656605SStefano Zampini 
394306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
394406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
39452958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
394606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
394706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);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;
395106656605SStefano Zampini   if (isLU || isILU || 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;
3960ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
396122db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
396206656605SStefano Zampini   } else {
396306656605SStefano Zampini     F = NULL;
396406656605SStefano Zampini   }
396506656605SStefano Zampini 
3966c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3967c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3968c58f9fdbSStefano Zampini   if (F) {
3969ea799195SBarry Smith     MatSolverType solver;
3970c58f9fdbSStefano Zampini 
39713ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3972c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3973c58f9fdbSStefano Zampini   }
3974c58f9fdbSStefano Zampini 
3975ffd830a3SStefano Zampini   /* allocate workspace */
3976ffd830a3SStefano Zampini   n = 0;
3977ffd830a3SStefano Zampini   if (n_constraints) {
3978ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3979ffd830a3SStefano Zampini   }
3980ffd830a3SStefano Zampini   if (n_vertices) {
3981ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3982ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3983ffd830a3SStefano Zampini   }
39842a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39852a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39862a3a6641Sstefano_zampini   }
3987ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3988ffd830a3SStefano Zampini 
39895cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39905cbda25cSStefano Zampini   dummy_vec = NULL;
39915cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
3992c72cccf8SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec);CHKERRQ(ierr);
3993c72cccf8SStefano Zampini     ierr = VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE);CHKERRQ(ierr);
3994c72cccf8SStefano Zampini     ierr = VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name);CHKERRQ(ierr);
39955cbda25cSStefano Zampini   }
39965cbda25cSStefano Zampini 
399788ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
399888ebb749SStefano Zampini   if (n_constraints) {
3999837cedc9SStefano Zampini     Mat         M3,C_B;
400006656605SStefano Zampini     IS          is_aux;
400180677318SStefano Zampini     PetscScalar *array,*array2;
400206656605SStefano Zampini 
4003f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
400480677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
400588ebb749SStefano Zampini 
400625084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
400725084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
40087dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
40097dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
401088ebb749SStefano Zampini 
401180677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
401280677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
4013c58f9fdbSStefano Zampini     if (!sparserhs) {
4014*580bdb30SBarry Smith       ierr = PetscArrayzero(work,lda_rhs*n_constraints);CHKERRQ(ierr);
401588ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
401606656605SStefano Zampini         const PetscScalar *row_cmat_values;
401706656605SStefano Zampini         const PetscInt    *row_cmat_indices;
401806656605SStefano Zampini         PetscInt          size_of_constraint,j;
401988ebb749SStefano Zampini 
402006656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402106656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
4022ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
402306656605SStefano Zampini         }
402406656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402506656605SStefano Zampini       }
4026c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
4027c58f9fdbSStefano Zampini     } else {
4028c58f9fdbSStefano Zampini       Mat tC_CR;
4029c58f9fdbSStefano Zampini 
4030c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4031c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
4032c58f9fdbSStefano Zampini         PetscScalar *aa;
4033c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
4034c58f9fdbSStefano Zampini         PetscBool   done;
4035c58f9fdbSStefano Zampini 
4036c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
403713903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4038c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
4039c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
4040c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
404113903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4042c58f9fdbSStefano Zampini       } else {
4043c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
4044c58f9fdbSStefano Zampini         tC_CR = C_CR;
4045c58f9fdbSStefano Zampini       }
4046c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
4047c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
4048c58f9fdbSStefano Zampini     }
4049ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
405006656605SStefano Zampini     if (F) {
4051a3df083aSStefano Zampini       if (need_benign_correction) {
4052df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4053a3df083aSStefano Zampini 
405472b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
4055*580bdb30SBarry Smith         ierr = PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n);CHKERRQ(ierr);
4056a3df083aSStefano Zampini       }
4057c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
4058a3df083aSStefano Zampini       if (need_benign_correction) {
4059a3df083aSStefano Zampini         PetscScalar        *marr;
4060df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4061a3df083aSStefano Zampini 
4062a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
40635cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40645cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40655cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40665cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40675cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40685cbda25cSStefano Zampini           }
40695cbda25cSStefano Zampini         } else {
4070a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
4071a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40725cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4073a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4074a3df083aSStefano Zampini           }
40755cbda25cSStefano Zampini         }
4076a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
4077a3df083aSStefano Zampini       }
407806656605SStefano Zampini     } else {
407980677318SStefano Zampini       PetscScalar *marr;
408080677318SStefano Zampini 
408180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
408206656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
4083ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4084ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
408506656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4086c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
408706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
408806656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
408906656605SStefano Zampini       }
409080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
409106656605SStefano Zampini     }
4092c58f9fdbSStefano Zampini     if (sparserhs) {
4093c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4094c58f9fdbSStefano Zampini     }
4095c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
409680677318SStefano Zampini     if (!pcbddc->switch_static) {
409780677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
409880677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
409980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
410080677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4101ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
410280677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
410380677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
410480677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
410580677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
410680677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
410780677318SStefano Zampini       }
410880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
410980677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
411072b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
411180677318SStefano Zampini     } else {
4112ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4113ffd830a3SStefano Zampini         IS dummy;
4114ffd830a3SStefano Zampini 
4115ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
41167dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
4117ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
4118ffd830a3SStefano Zampini       } else {
411980677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
412080677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4121ffd830a3SStefano Zampini       }
412225084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
412380677318SStefano Zampini     }
412480677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
412580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
412680677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
412780677318SStefano Zampini     if (isCHOL) {
412880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
412980677318SStefano Zampini     } else {
413025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
413180677318SStefano Zampini     }
4132837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
413380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
4134837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
413572b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
4136837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
4137837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
4138f4ddd8eeSStefano Zampini   }
4139fc227af8SStefano Zampini 
4140fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
414188ebb749SStefano Zampini   if (n_vertices) {
414206656605SStefano Zampini     IS        is_aux;
4143c58f9fdbSStefano Zampini     PetscBool isseqaij;
41443a50541eSStefano Zampini 
4145b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
41466816873aSStefano Zampini       IS tis;
41476816873aSStefano Zampini 
41486816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
41496816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
41506816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
41516816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
41526816873aSStefano Zampini     } else {
41533a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
41546816873aSStefano Zampini     }
41557dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
41567dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
4157c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
4158c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
4159c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4160c58f9fdbSStefano Zampini     }
41617dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
416225084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
416388ebb749SStefano Zampini   }
416488ebb749SStefano Zampini 
416588ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4166f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
416706656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
416806656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
416906656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
417006656605SStefano Zampini     }
4171f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
417206656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
417306656605SStefano Zampini       PetscScalar *marray;
417406656605SStefano Zampini 
417506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
417606656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4177f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4178f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4179f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4180f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4181f4ddd8eeSStefano Zampini     }
4182f4ddd8eeSStefano Zampini   }
418306656605SStefano Zampini 
4184f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4185a6e023c1Sstefano_zampini     PetscScalar *marr;
418688ebb749SStefano Zampini 
4187a6e023c1Sstefano_zampini     /* memory size */
418806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4189a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4190a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4191a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4192a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4193a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
41948eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4195a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4196a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
419788ebb749SStefano Zampini     }
41983301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4199a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4200a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
42018eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4202a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
420388ebb749SStefano Zampini       }
420488ebb749SStefano Zampini     } else {
4205c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4206c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
42071b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4208c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4209c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4210c0553b1fSStefano Zampini       }
421188ebb749SStefano Zampini     }
421206656605SStefano Zampini   }
4213019a44ceSStefano Zampini 
421406656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
42154f1b2e48SStefano Zampini   p0_lidx_I = NULL;
42164f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4217d12edf2fSStefano Zampini     const PetscInt *idxs;
4218d12edf2fSStefano Zampini 
4219d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
42204f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
42214f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
42224f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
42234f1b2e48SStefano Zampini     }
4224d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4225d12edf2fSStefano Zampini   }
4226d16cbb6bSStefano Zampini 
422706656605SStefano Zampini   /* vertices */
422806656605SStefano Zampini   if (n_vertices) {
4229c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
423016f15bc4SStefano Zampini 
4231af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
423204708bb6SStefano Zampini 
423316f15bc4SStefano Zampini     if (n_R) {
423414393ed6SStefano Zampini       Mat               A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
423506656605SStefano Zampini       PetscBLASInt      B_N,B_one = 1;
42361683a169SBarry Smith       const PetscScalar *x;
42371683a169SBarry Smith       PetscScalar       *y;
423806656605SStefano Zampini 
423921eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
424014393ed6SStefano Zampini       if (need_benign_correction) {
424114393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
424214393ed6SStefano Zampini         IS                     is_p0;
424314393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
424414393ed6SStefano Zampini 
424514393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
424614393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
424714393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
42486080607fSStefano 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);
424914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
425014393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
42517dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
425214393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
425314393ed6SStefano Zampini       }
425414393ed6SStefano Zampini 
4255c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4256c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4257ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4258af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4259ffd830a3SStefano Zampini         } else {
4260ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4261ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4262ca92afb2SStefano Zampini           PetscInt       n;
4263ca92afb2SStefano Zampini           PetscBool      flg_row;
4264ffd830a3SStefano Zampini 
4265ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4266*580bdb30SBarry Smith           ierr = PetscArrayzero(array,lda_rhs*n_vertices);CHKERRQ(ierr);
42679d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4268ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4269ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4270ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4271ca92afb2SStefano Zampini             PetscInt j;
4272ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4273ffd830a3SStefano Zampini           }
4274ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4275ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4276ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4277ffd830a3SStefano Zampini         }
4278a3df083aSStefano Zampini         if (need_benign_correction) {
4279df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4280a3df083aSStefano Zampini           PetscScalar        *marr;
4281a3df083aSStefano Zampini 
4282a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
428314393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
428414393ed6SStefano Zampini 
428514393ed6SStefano Zampini                  | 0 0  0 | (V)
428614393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
428714393ed6SStefano Zampini                  | 0 0 -1 | (p0)
428814393ed6SStefano Zampini 
428914393ed6SStefano Zampini           */
4290df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
429114393ed6SStefano Zampini             const PetscScalar *vals;
429214393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
429314393ed6SStefano Zampini             PetscInt          n,j,nz;
429414393ed6SStefano Zampini 
4295df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4296df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
429714393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
429814393ed6SStefano Zampini             for (j=0;j<n;j++) {
429914393ed6SStefano Zampini               PetscScalar val = vals[j];
430014393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
430114393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
430214393ed6SStefano Zampini             }
430314393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4304df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
430514393ed6SStefano Zampini           }
430672b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
430772b8c272SStefano Zampini         }
4308c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4309c58f9fdbSStefano Zampini         Brhs = A_RV;
4310c58f9fdbSStefano Zampini       } else {
4311c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4312c58f9fdbSStefano Zampini 
4313c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4314fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4315c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4316c58f9fdbSStefano Zampini         } else {
4317c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4318c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4319c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4320c58f9fdbSStefano Zampini           A_RVT = A_VR;
4321c58f9fdbSStefano Zampini         }
4322c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4323c58f9fdbSStefano Zampini           PetscScalar *aa;
4324c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4325c58f9fdbSStefano Zampini           PetscBool   done;
4326c58f9fdbSStefano Zampini 
4327c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
432813903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4329c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4330c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4331c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
433213903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4333c58f9fdbSStefano Zampini         } else {
4334c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4335c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4336c58f9fdbSStefano Zampini         }
4337c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4338c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4339c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4340c58f9fdbSStefano Zampini       }
434172b8c272SStefano Zampini       if (F) {
434214393ed6SStefano Zampini         /* need to correct the rhs */
434372b8c272SStefano Zampini         if (need_benign_correction) {
434472b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
434572b8c272SStefano Zampini           PetscScalar        *marr;
434672b8c272SStefano Zampini 
4347c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
43485cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43495cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43505cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43515cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
43525cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43535cbda25cSStefano Zampini             }
43545cbda25cSStefano Zampini           } else {
4355a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4356a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43575cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4358a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4359a3df083aSStefano Zampini             }
43605cbda25cSStefano Zampini           }
4361c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4362a3df083aSStefano Zampini         }
4363c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4364c58f9fdbSStefano Zampini         if (restoreavr) {
4365c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4366c58f9fdbSStefano Zampini         }
436714393ed6SStefano Zampini         /* need to correct the solution */
4368a3df083aSStefano Zampini         if (need_benign_correction) {
4369df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4370a3df083aSStefano Zampini           PetscScalar        *marr;
4371a3df083aSStefano Zampini 
4372a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
43735cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43745cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43755cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43765cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
43775cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43785cbda25cSStefano Zampini             }
43795cbda25cSStefano Zampini           } else {
4380a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4381a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43825cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4383a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4384a3df083aSStefano Zampini             }
43855cbda25cSStefano Zampini           }
4386a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4387a3df083aSStefano Zampini         }
438806656605SStefano Zampini       } else {
4389c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
439006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4391ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4392ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
439306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4394c0decd05SBarry Smith           ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
439506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
439606656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
439706656605SStefano Zampini         }
4398c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
439906656605SStefano Zampini       }
440080677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4401c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4402ffd830a3SStefano Zampini       /* S_VV and S_CV */
440306656605SStefano Zampini       if (n_constraints) {
440406656605SStefano Zampini         Mat B;
440580677318SStefano Zampini 
4406*580bdb30SBarry Smith         ierr = PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices);CHKERRQ(ierr);
440780677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4408ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4409ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
441080677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
441180677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
441280677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
441380677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
441480677318SStefano Zampini         }
4415ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
441680677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
441780677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4418ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
441980677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
442006656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4421ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4422ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
442306656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
442406656605SStefano Zampini       }
4425ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4426ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4427ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4428ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4429ffd830a3SStefano Zampini       }
443006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
443114393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
443214393ed6SStefano Zampini       if (need_benign_correction) {
4433df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
443414393ed6SStefano Zampini         PetscScalar      *marr,*sums;
443514393ed6SStefano Zampini 
443614393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4437f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4438df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
443914393ed6SStefano Zampini           const PetscScalar *vals;
444014393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
444114393ed6SStefano Zampini           PetscInt          n,j,nz;
444214393ed6SStefano Zampini 
4443df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4444df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
444514393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
444614393ed6SStefano Zampini             PetscInt k;
444714393ed6SStefano Zampini             sums[j] = 0.;
444814393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
444914393ed6SStefano Zampini           }
445014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
445114393ed6SStefano Zampini           for (j=0;j<n;j++) {
445214393ed6SStefano Zampini             PetscScalar val = vals[j];
445314393ed6SStefano Zampini             PetscInt k;
445414393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
445514393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
445614393ed6SStefano Zampini             }
445714393ed6SStefano Zampini           }
445814393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4459df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
446014393ed6SStefano Zampini         }
446114393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4462f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
446314393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
446414393ed6SStefano Zampini       }
446580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
446606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
44671683a169SBarry Smith       ierr = MatDenseGetArrayRead(A_VV,&x);CHKERRQ(ierr);
446806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
446906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
44701683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(A_VV,&x);CHKERRQ(ierr);
447106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
447206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4473d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4474019a44ceSStefano Zampini     } else {
4475d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4476d16cbb6bSStefano Zampini     }
447721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4478d16cbb6bSStefano Zampini 
447906656605SStefano Zampini     /* coarse basis functions */
448006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
448116f15bc4SStefano Zampini       PetscScalar *y;
448216f15bc4SStefano Zampini 
4483ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
448406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
448506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
448606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
448906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
449006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
449106656605SStefano Zampini 
449206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
44934f1b2e48SStefano Zampini         PetscInt j;
44944f1b2e48SStefano Zampini 
449506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
449606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
449706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
45004f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
450106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
450206656605SStefano Zampini       }
450306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
450406656605SStefano Zampini     }
450504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
450604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
450706656605SStefano Zampini   }
45085cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
450906656605SStefano Zampini 
451006656605SStefano Zampini   if (n_constraints) {
451106656605SStefano Zampini     Mat B;
451206656605SStefano Zampini 
4513ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
451406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
451580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
451606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
451706656605SStefano Zampini     if (n_vertices) {
451803dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
451980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
452080677318SStefano Zampini       } else {
452180677318SStefano Zampini         Mat S_VCt;
452280677318SStefano Zampini 
4523ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4524ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
452572b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4526ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4527ffd830a3SStefano Zampini         }
452880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
452980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
453080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
453180677318SStefano Zampini       }
453206656605SStefano Zampini     }
453306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
453406656605SStefano Zampini     /* coarse basis functions */
453506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
453606656605SStefano Zampini       PetscScalar *y;
453706656605SStefano Zampini 
4538ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
453906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
454006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
454106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
454406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
454506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45464f1b2e48SStefano Zampini         PetscInt j;
45474f1b2e48SStefano Zampini 
454806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
454906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
455006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
455106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
455206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
45534f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
455406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
455506656605SStefano Zampini       }
455606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
455706656605SStefano Zampini     }
455806656605SStefano Zampini   }
455980677318SStefano Zampini   if (n_constraints) {
456080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
456180677318SStefano Zampini   }
45624f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
456372b8c272SStefano Zampini 
456472b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
456572b8c272SStefano Zampini   if (pcbddc->benign_n) {
456672b8c272SStefano Zampini     Mat               B0_B,B0_BPHI;
456772b8c272SStefano Zampini     IS                is_dummy;
45681683a169SBarry Smith     const PetscScalar *data;
456972b8c272SStefano Zampini     PetscInt          j;
457072b8c272SStefano Zampini 
457172b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
45727dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
457372b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
457472b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
457586c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
45761683a169SBarry Smith     ierr = MatDenseGetArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
457772b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
457872b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
457972b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
458072b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
458172b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
458272b8c272SStefano Zampini       }
458372b8c272SStefano Zampini     }
45841683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
458572b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
458672b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
458772b8c272SStefano Zampini   }
4588019a44ceSStefano Zampini 
458906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
45903301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4591ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4592ffd830a3SStefano Zampini     PetscScalar *marray;
459306656605SStefano Zampini 
459406656605SStefano Zampini     if (n_constraints) {
4595ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
459606656605SStefano Zampini 
4597abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
459806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4599ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
460016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
460106656605SStefano Zampini       if (n_vertices) {
4602ffd830a3SStefano Zampini         Mat S_VCT;
460306656605SStefano Zampini 
460406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4605ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
460616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
460706656605SStefano Zampini       }
4608ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
46095b782168SStefano Zampini     } else {
46105b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
461106656605SStefano Zampini     }
461216f15bc4SStefano Zampini     if (n_vertices && n_R) {
4613ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4614ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4615ffd830a3SStefano Zampini       PetscInt       n;
4616ffd830a3SStefano Zampini       PetscBool      flg_row;
461706656605SStefano Zampini 
4618ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4619af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4620ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4621ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4622ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4623ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4624ffd830a3SStefano Zampini         PetscInt j;
4625ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4626ffd830a3SStefano Zampini       }
4627ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4628ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4629ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
463006656605SStefano Zampini     }
463106656605SStefano Zampini 
4632ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4633abc8f43dSstefano_zampini     if (n_vertices) {
4634ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4635ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4636ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4637ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
463806656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4639c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
464006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
464106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
464206656605SStefano Zampini       }
4643ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4644abc8f43dSstefano_zampini     }
46455b782168SStefano Zampini     if (B_C) {
4646ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4647ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4648ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4649ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4650ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4651c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
4652ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4653ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
465406656605SStefano Zampini       }
4655ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
46565b782168SStefano Zampini     }
465706656605SStefano Zampini     /* coarse basis functions */
465806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
465906656605SStefano Zampini       PetscScalar *y;
466006656605SStefano Zampini 
4661ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
466206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
466306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
466406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
466506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
466606656605SStefano Zampini       if (i<n_vertices) {
466706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
466806656605SStefano Zampini       }
466906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
467006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
467106656605SStefano Zampini 
467206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
467306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
467406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
467506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
467606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
467706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
467806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
467906656605SStefano Zampini       }
468006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
468106656605SStefano Zampini     }
4682ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4683ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
468406656605SStefano Zampini   }
4685a6e023c1Sstefano_zampini 
4686d62866d3SStefano Zampini   /* free memory */
468788ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
468806656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
468906656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
469006656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
469106656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4692d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4693d62866d3SStefano Zampini   if (n_vertices) {
4694d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4695d62866d3SStefano Zampini   }
4696d62866d3SStefano Zampini   if (n_constraints) {
4697d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4698d62866d3SStefano Zampini   }
469988ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
470088ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
470188ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4702d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
470388ebb749SStefano Zampini     Mat         coarse_sub_mat;
470425084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
470588ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
470688ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
470788ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
47088bec7fa6SStefano Zampini     Mat         C_B,CPHI;
47098bec7fa6SStefano Zampini     IS          is_dummy;
47108bec7fa6SStefano Zampini     Vec         mones;
471188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
471288ebb749SStefano Zampini     PetscReal   real_value;
471388ebb749SStefano Zampini 
4714a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4715a3df083aSStefano Zampini       Mat A;
4716a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
47177dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
47187dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
47197dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
47207dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4721a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4722a3df083aSStefano Zampini     } else {
472388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
472488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
472588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
472688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4727a3df083aSStefano Zampini     }
472888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
472988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4730ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
473188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
473288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
473388ebb749SStefano Zampini     }
473488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
473588ebb749SStefano Zampini 
473625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47373301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
473825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4739ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
474088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
474188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
474288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
474388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
474488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
474588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
474688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
474788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
474888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
474988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
475188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
475288ebb749SStefano Zampini     } else {
475388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
475488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
475588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
475788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
475888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
475988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
476088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
476188ebb749SStefano Zampini     }
476288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
476388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
476488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4765511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
47664f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4767fc227af8SStefano Zampini       Mat               B0_B,B0_BPHI;
47681683a169SBarry Smith       const PetscScalar *data2;
47691683a169SBarry Smith       PetscScalar       *data;
47704f1b2e48SStefano Zampini       PetscInt          j;
4771d12edf2fSStefano Zampini 
47724f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
47737dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4774d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
477586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4776d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
47771683a169SBarry Smith       ierr = MatDenseGetArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
47784f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
47794f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4780d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
47814f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
47824f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
47834f1b2e48SStefano Zampini         }
4784d12edf2fSStefano Zampini       }
4785d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
47861683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
4787d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4788d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4789d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4790d12edf2fSStefano Zampini     }
4791d12edf2fSStefano Zampini #if 0
4792d12edf2fSStefano Zampini   {
4793d12edf2fSStefano Zampini     PetscViewer viewer;
4794d12edf2fSStefano Zampini     char filename[256];
4795ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4796d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4797a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4798ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4799ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4800ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4801d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4802a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4803ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4804ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
480572b8c272SStefano Zampini     }
4806ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4807ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4808ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4809ffd830a3SStefano Zampini     }
4810ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4811ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4812ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4813ffd830a3SStefano Zampini     }
481472b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4815ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4816ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4817ffd830a3SStefano Zampini     }
4818fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4819fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4820fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4821fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4822fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4823fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4824fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4825fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4826fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4827fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4828d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4829d12edf2fSStefano Zampini   }
4830d12edf2fSStefano Zampini #endif
483181d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
48328bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
48331575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
483406656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
48358bec7fa6SStefano Zampini 
48368bec7fa6SStefano Zampini     /* check constraints */
4837a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
48387dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
48394f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
48408bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4841a00504b5SStefano Zampini     } else {
4842a00504b5SStefano Zampini       PetscScalar *data;
4843a00504b5SStefano Zampini       Mat         tmat;
4844a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4845a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4846a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4847a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4848a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4849a00504b5SStefano Zampini     }
48508bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
48518bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
48528bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
48538bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4854bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4855ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4856bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4857bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4858bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4859bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4860bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
486188ebb749SStefano Zampini     }
48628bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
48638bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
48648bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
48658bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
486625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
486788ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
486888ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
486988ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
487088ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
487188ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
487288ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
487388ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
487488ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
487588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
487688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4877ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
487888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
487988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
488088ebb749SStefano Zampini     }
488188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
488288ebb749SStefano Zampini   }
48838629588bSStefano Zampini   /* get back data */
48848629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
488543371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
488688ebb749SStefano Zampini   PetscFunctionReturn(0);
488788ebb749SStefano Zampini }
488888ebb749SStefano Zampini 
48897dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4890aa0d41d4SStefano Zampini {
4891d65f70fdSStefano Zampini   Mat            *work_mat;
4892d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4893d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4894c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4895aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4896aa0d41d4SStefano Zampini 
4897aa0d41d4SStefano Zampini   PetscFunctionBegin;
4898d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4899d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4900d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4901d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4902aa0d41d4SStefano Zampini 
4903d65f70fdSStefano Zampini   if (!rsorted) {
4904906d46d4SStefano Zampini     const PetscInt *idxs;
4905906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4906aa0d41d4SStefano Zampini 
4907d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4908d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4909d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4910d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4911aa0d41d4SStefano Zampini     }
4912d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4913d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4914d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4915d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4916aa0d41d4SStefano Zampini     }
4917d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4918d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4919d65f70fdSStefano Zampini   } else {
4920d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4921d65f70fdSStefano Zampini     isrow_s = isrow;
4922aa0d41d4SStefano Zampini   }
4923906d46d4SStefano Zampini 
4924d65f70fdSStefano Zampini   if (!csorted) {
4925d65f70fdSStefano Zampini     if (isrow == iscol) {
4926d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4927d65f70fdSStefano Zampini       iscol_s = isrow_s;
4928d65f70fdSStefano Zampini     } else {
4929d65f70fdSStefano Zampini       const PetscInt *idxs;
4930d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4931906d46d4SStefano Zampini 
4932d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4933d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4934d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4935d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4936d65f70fdSStefano Zampini       }
4937d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4938d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4939d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4940d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4941d65f70fdSStefano Zampini       }
4942d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4943d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4944d65f70fdSStefano Zampini     }
4945d65f70fdSStefano Zampini   } else {
4946d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4947d65f70fdSStefano Zampini     iscol_s = iscol;
4948d65f70fdSStefano Zampini   }
4949d65f70fdSStefano Zampini 
49507dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4951d65f70fdSStefano Zampini 
4952d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4953906d46d4SStefano Zampini     Mat      new_mat;
4954d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4955906d46d4SStefano Zampini 
4956d65f70fdSStefano Zampini     if (!rsorted) {
4957d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4958d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4959d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4960d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4961906d46d4SStefano Zampini       }
4962d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4963d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4964d65f70fdSStefano Zampini     } else {
4965d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4966906d46d4SStefano Zampini     }
4967d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4968d65f70fdSStefano Zampini 
4969d65f70fdSStefano Zampini     if (!csorted) {
4970d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4971d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4972d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4973d65f70fdSStefano Zampini       } else {
4974d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4975f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4976d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4977d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4978d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4979d65f70fdSStefano Zampini         }
4980d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4981d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4982d65f70fdSStefano Zampini       }
4983d65f70fdSStefano Zampini     } else {
4984d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4985d65f70fdSStefano Zampini     }
4986d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4987d65f70fdSStefano Zampini 
4988d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4989d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4990d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4991d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4992d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4993d65f70fdSStefano Zampini   }
4994d65f70fdSStefano Zampini 
4995d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4996d65f70fdSStefano Zampini   *B = work_mat[0];
4997d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4998d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4999d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
5000d65f70fdSStefano Zampini   PetscFunctionReturn(0);
5001d65f70fdSStefano Zampini }
5002d65f70fdSStefano Zampini 
50035e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
5004aa0d41d4SStefano Zampini {
5005aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
50065e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5007022d8d2bSstefano_zampini   Mat            new_mat,lA;
50085e8657edSStefano Zampini   IS             is_local,is_global;
5009d65f70fdSStefano Zampini   PetscInt       local_size;
5010d65f70fdSStefano Zampini   PetscBool      isseqaij;
5011aa0d41d4SStefano Zampini   PetscErrorCode ierr;
5012aa0d41d4SStefano Zampini 
5013aa0d41d4SStefano Zampini   PetscFunctionBegin;
5014aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
50155e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
50165e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
5017b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
5018aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
50197dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
5020aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
5021906d46d4SStefano Zampini 
5022906d46d4SStefano Zampini   /* check */
5023906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
5024906d46d4SStefano Zampini     Vec       x,x_change;
5025906d46d4SStefano Zampini     PetscReal error;
5026906d46d4SStefano Zampini 
50275e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
5028906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
50295e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
5030e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5031e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5032d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
503388428137SStefano Zampini     if (!pcbddc->change_interior) {
503488428137SStefano Zampini       const PetscScalar *x,*y,*v;
503588428137SStefano Zampini       PetscReal         lerror = 0.;
503688428137SStefano Zampini       PetscInt          i;
503788428137SStefano Zampini 
503888428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
503988428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
504088428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
504188428137SStefano Zampini       for (i=0;i<local_size;i++)
504288428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
504388428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
504488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
504588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
504688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
504788428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5048637e8532SStefano Zampini       if (error > PETSC_SMALL) {
5049637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
50506080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",error);
5051637e8532SStefano Zampini         } else {
50526080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",error);
5053637e8532SStefano Zampini         }
5054637e8532SStefano Zampini       }
505588428137SStefano Zampini     }
5056e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5057e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5058906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5059906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5060637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5061637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
50626080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
5063637e8532SStefano Zampini       } else {
50646080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",error);
5065637e8532SStefano Zampini       }
5066637e8532SStefano Zampini     }
5067906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
5068906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5069906d46d4SStefano Zampini   }
5070906d46d4SStefano Zampini 
5071022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
5072022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
5073022d8d2bSstefano_zampini 
507422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
50759b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
507622d5777bSStefano Zampini   if (isseqaij) {
5077a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5078a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
5079022d8d2bSstefano_zampini     if (lA) {
5080022d8d2bSstefano_zampini       Mat work;
5081022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5082022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5083022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5084022d8d2bSstefano_zampini     }
5085aa0d41d4SStefano Zampini   } else {
5086a00504b5SStefano Zampini     Mat work_mat;
50871cf9b237SStefano Zampini 
5088a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5089aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5090a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
50911d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
5092022d8d2bSstefano_zampini     if (lA) {
5093022d8d2bSstefano_zampini       Mat work;
5094022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5095022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5096022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5097022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5098022d8d2bSstefano_zampini     }
5099aa0d41d4SStefano Zampini   }
51003301b35fSStefano Zampini   if (matis->A->symmetric_set) {
51013301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
5102e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
51033301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
5104e496cd5dSStefano Zampini #endif
51053301b35fSStefano Zampini   }
5106d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
5107aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
5108aa0d41d4SStefano Zampini }
5109aa0d41d4SStefano Zampini 
51108ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
5111a64d13efSStefano Zampini {
5112a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
5113a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5114d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
511553892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
51163a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
51173a50541eSStefano Zampini   PetscInt        vbs,bs;
51186816873aSStefano Zampini   PetscBT         bitmask=NULL;
5119a64d13efSStefano Zampini   PetscErrorCode  ierr;
5120a64d13efSStefano Zampini 
5121a64d13efSStefano Zampini   PetscFunctionBegin;
5122b23d619eSStefano Zampini   /*
5123b23d619eSStefano Zampini     No need to setup local scatters if
5124b23d619eSStefano Zampini       - primal space is unchanged
5125b23d619eSStefano Zampini         AND
5126b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
5127b23d619eSStefano Zampini         AND
5128b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5129b23d619eSStefano Zampini   */
5130b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5131f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5132f4ddd8eeSStefano Zampini   }
5133f4ddd8eeSStefano Zampini   /* destroy old objects */
5134f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
5135f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
5136f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
5137a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5138b371cd4fSStefano Zampini   n_B = pcis->n_B;
5139b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5140b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
51413a50541eSStefano Zampini 
5142a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
51436816873aSStefano Zampini 
514453892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5145b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
5146854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
5147a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
5148a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
51490e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
5150a64d13efSStefano Zampini     }
5151a64d13efSStefano Zampini 
5152a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
51534641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
51546816873aSStefano Zampini         idx_R_local[n_R++] = i;
5155a64d13efSStefano Zampini       }
5156a64d13efSStefano Zampini     }
5157df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5158df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
51596816873aSStefano Zampini 
5160df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5161df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
51626816873aSStefano Zampini   }
51633a50541eSStefano Zampini 
51643a50541eSStefano Zampini   /* Block code */
51653a50541eSStefano Zampini   vbs = 1;
51663a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
51673a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
51683a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
51693a50541eSStefano Zampini     PetscInt  *vary;
5170b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5171785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
5172*580bdb30SBarry Smith       ierr = PetscArrayzero(vary,pcis->n/bs);CHKERRQ(ierr);
5173d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5174d3df7717SStefano 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 */
51750e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5176d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
51773a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
51783a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
51793a50541eSStefano Zampini           break;
51803a50541eSStefano Zampini         }
51813a50541eSStefano Zampini       }
5182d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5183d3df7717SStefano Zampini     } else {
5184d3df7717SStefano Zampini       /* Verify directly the R set */
5185d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5186d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5187d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5188d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5189d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5190d3df7717SStefano Zampini             break;
5191d3df7717SStefano Zampini           }
5192d3df7717SStefano Zampini         }
5193d3df7717SStefano Zampini       }
5194d3df7717SStefano Zampini     }
51953a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
51963a50541eSStefano Zampini       vbs = bs;
51973a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
51983a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
51993a50541eSStefano Zampini       }
52003a50541eSStefano Zampini     }
52013a50541eSStefano Zampini   }
52023a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5203b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5204df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
520553892102SStefano Zampini 
5206df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5207df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
520853892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5209df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
521053892102SStefano Zampini   } else {
52113a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
521253892102SStefano Zampini   }
5213a64d13efSStefano Zampini 
5214a64d13efSStefano Zampini   /* print some info if requested */
5215a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5216a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5217a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
52181575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5219a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
52206080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %D, dirichlet_size = %D, boundary_size = %D\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
52216080607fSStefano 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);
5222a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5223a64d13efSStefano Zampini   }
5224a64d13efSStefano Zampini 
5225a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5226b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
52276816873aSStefano Zampini     IS       is_aux1,is_aux2;
52286816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
52296816873aSStefano Zampini 
52303a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5231854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5232854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5233a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
52344641a718SStefano Zampini     for (i=0; i<n_D; i++) {
52354641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
52364641a718SStefano Zampini     }
5237a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5238a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
52394641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
52404641a718SStefano Zampini         aux_array1[j++] = i;
5241a64d13efSStefano Zampini       }
5242a64d13efSStefano Zampini     }
5243a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5244a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5245a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
52464641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
52474641a718SStefano Zampini         aux_array2[j++] = i;
5248a64d13efSStefano Zampini       }
5249a64d13efSStefano Zampini     }
5250a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5251a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
52529448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5253a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5254a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5255a64d13efSStefano Zampini 
52568eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5257785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5258a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
52594641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
52604641a718SStefano Zampini           aux_array1[j++] = i;
5261a64d13efSStefano Zampini         }
5262a64d13efSStefano Zampini       }
5263a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
52649448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5265a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5266a64d13efSStefano Zampini     }
52674641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
52683a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5269d62866d3SStefano Zampini   } else {
5270df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
52716816873aSStefano Zampini     IS                 tis;
52726816873aSStefano Zampini     PetscInt           schur_size;
52736816873aSStefano Zampini 
5274df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
52756816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
52769448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
52776816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
52786816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
52796816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
52809448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
52816816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5282d62866d3SStefano Zampini     }
5283d62866d3SStefano Zampini   }
5284a64d13efSStefano Zampini   PetscFunctionReturn(0);
5285a64d13efSStefano Zampini }
5286a64d13efSStefano Zampini 
528792cccca0SStefano Zampini static PetscErrorCode MatNullSpacePropagate_Private(Mat A, IS is, Mat B)
528892cccca0SStefano Zampini {
528992cccca0SStefano Zampini   MatNullSpace   NullSpace;
529092cccca0SStefano Zampini   Mat            dmat;
529192cccca0SStefano Zampini   const Vec      *nullvecs;
529292cccca0SStefano Zampini   Vec            v,v2,*nullvecs2;
529392cccca0SStefano Zampini   VecScatter     sct;
529492cccca0SStefano Zampini   PetscInt       k,nnsp_size,bsiz,n,N,bs;
529592cccca0SStefano Zampini   PetscBool      nnsp_has_cnst;
529692cccca0SStefano Zampini   PetscErrorCode ierr;
529792cccca0SStefano Zampini 
529892cccca0SStefano Zampini   PetscFunctionBegin;
529992cccca0SStefano Zampini   ierr = MatGetNullSpace(B,&NullSpace);CHKERRQ(ierr);
530092cccca0SStefano Zampini   if (!NullSpace) {
530192cccca0SStefano Zampini     ierr = MatGetNearNullSpace(B,&NullSpace);CHKERRQ(ierr);
530292cccca0SStefano Zampini   }
530392cccca0SStefano Zampini   if (NullSpace) PetscFunctionReturn(0);
530492cccca0SStefano Zampini   ierr = MatGetNullSpace(A,&NullSpace);CHKERRQ(ierr);
530592cccca0SStefano Zampini   if (!NullSpace) {
530692cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A,&NullSpace);CHKERRQ(ierr);
530792cccca0SStefano Zampini   }
530892cccca0SStefano Zampini   if (!NullSpace) PetscFunctionReturn(0);
530992cccca0SStefano Zampini   ierr = MatCreateVecs(A,&v,NULL);CHKERRQ(ierr);
531092cccca0SStefano Zampini   ierr = MatCreateVecs(B,&v2,NULL);CHKERRQ(ierr);
53119448b7f1SJunchao Zhang   ierr = VecScatterCreate(v,is,v2,NULL,&sct);CHKERRQ(ierr);
531292cccca0SStefano Zampini   ierr = MatNullSpaceGetVecs(NullSpace,&nnsp_has_cnst,&nnsp_size,(const Vec**)&nullvecs);CHKERRQ(ierr);
531392cccca0SStefano Zampini   bsiz = nnsp_size+!!nnsp_has_cnst;
531492cccca0SStefano Zampini   ierr = PetscMalloc1(bsiz,&nullvecs2);CHKERRQ(ierr);
531592cccca0SStefano Zampini   ierr = VecGetBlockSize(v2,&bs);CHKERRQ(ierr);
531692cccca0SStefano Zampini   ierr = VecGetSize(v2,&N);CHKERRQ(ierr);
531792cccca0SStefano Zampini   ierr = VecGetLocalSize(v2,&n);CHKERRQ(ierr);
531892cccca0SStefano Zampini   ierr = MatCreateDense(PetscObjectComm((PetscObject)B),n,PETSC_DECIDE,N,bsiz,NULL,&dmat);CHKERRQ(ierr);
531992cccca0SStefano Zampini   for (k=0;k<nnsp_size;k++) {
532092cccca0SStefano Zampini     PetscScalar *arr;
532192cccca0SStefano Zampini 
532292cccca0SStefano Zampini     ierr = MatDenseGetColumn(dmat,k,&arr);CHKERRQ(ierr);
532392cccca0SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,arr,&nullvecs2[k]);CHKERRQ(ierr);
532492cccca0SStefano Zampini     ierr = VecScatterBegin(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
532592cccca0SStefano Zampini     ierr = VecScatterEnd(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
532692cccca0SStefano Zampini     ierr = MatDenseRestoreColumn(dmat,&arr);CHKERRQ(ierr);
532792cccca0SStefano Zampini   }
532892cccca0SStefano Zampini   if (nnsp_has_cnst) {
532992cccca0SStefano Zampini     PetscScalar *arr;
533092cccca0SStefano Zampini 
533192cccca0SStefano Zampini     ierr = MatDenseGetColumn(dmat,nnsp_size,&arr);CHKERRQ(ierr);
533292cccca0SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,arr,&nullvecs2[nnsp_size]);CHKERRQ(ierr);
533392cccca0SStefano Zampini     ierr = VecSet(nullvecs2[nnsp_size],1.0);CHKERRQ(ierr);
533492cccca0SStefano Zampini     ierr = MatDenseRestoreColumn(dmat,&arr);CHKERRQ(ierr);
533592cccca0SStefano Zampini   }
533692cccca0SStefano Zampini   ierr = PCBDDCOrthonormalizeVecs(bsiz,nullvecs2);CHKERRQ(ierr);
533792cccca0SStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)B),PETSC_FALSE,bsiz,nullvecs2,&NullSpace);CHKERRQ(ierr);
533892cccca0SStefano Zampini   ierr = PetscObjectCompose((PetscObject)NullSpace,"_PBDDC_Null_dmat",(PetscObject)dmat);CHKERRQ(ierr);
533992cccca0SStefano Zampini   ierr = MatDestroy(&dmat);CHKERRQ(ierr);
534092cccca0SStefano Zampini   for (k=0;k<bsiz;k++) {
534192cccca0SStefano Zampini     ierr = VecDestroy(&nullvecs2[k]);CHKERRQ(ierr);
534292cccca0SStefano Zampini   }
534392cccca0SStefano Zampini   ierr = PetscFree(nullvecs2);CHKERRQ(ierr);
534492cccca0SStefano Zampini   ierr = MatSetNearNullSpace(B,NullSpace);CHKERRQ(ierr);
534592cccca0SStefano Zampini   ierr = MatNullSpaceDestroy(&NullSpace);CHKERRQ(ierr);
534692cccca0SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
534792cccca0SStefano Zampini   ierr = VecDestroy(&v2);CHKERRQ(ierr);
534892cccca0SStefano Zampini   ierr = VecScatterDestroy(&sct);CHKERRQ(ierr);
534992cccca0SStefano Zampini   PetscFunctionReturn(0);
535092cccca0SStefano Zampini }
5351304d26faSStefano Zampini 
5352684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5353304d26faSStefano Zampini {
5354304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5355304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5356304d26faSStefano Zampini   PC             pc_temp;
5357304d26faSStefano Zampini   Mat            A_RR;
535892cccca0SStefano Zampini   MatNullSpace   nnsp;
5359f4ddd8eeSStefano Zampini   MatReuse       reuse;
5360304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5361304d26faSStefano Zampini   PetscReal      value;
536204708bb6SStefano Zampini   PetscInt       n_D,n_R;
536392cccca0SStefano Zampini   PetscBool      issbaij,opts;
5364304d26faSStefano Zampini   PetscErrorCode ierr;
536592cccca0SStefano Zampini   void           (*f)(void) = 0;
5366312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5367e604994aSStefano Zampini   size_t         len;
5368304d26faSStefano Zampini 
5369304d26faSStefano Zampini   PetscFunctionBegin;
537043371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5371e604994aSStefano Zampini   /* compute prefixes */
5372e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5373e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5374e604994aSStefano Zampini   if (!pcbddc->current_level) {
5375a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5376a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5377a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5378a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5379e604994aSStefano Zampini   } else {
538035529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5381e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5382e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5383312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5384312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5385a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
538634d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
538734d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5388a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5389a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5390a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5391a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5392e604994aSStefano Zampini   }
5393e604994aSStefano Zampini 
5394304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5395684f6988SStefano Zampini   if (dirichlet) {
5396d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5397450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
53986080607fSStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
5399450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5400a3df083aSStefano Zampini         Mat    A_IIn;
5401a3df083aSStefano Zampini 
5402a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5403a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5404a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5405a3df083aSStefano Zampini       }
5406450f8f5eSStefano Zampini     }
54073301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5408d1e098c7SStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
5409964fefecSStefano Zampini     }
5410ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5411964fefecSStefano Zampini     n_D  = pcis->n - pcis->n_B;
541292cccca0SStefano Zampini     opts = PETSC_FALSE;
5413304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
541492cccca0SStefano Zampini       opts = PETSC_TRUE;
5415304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5416304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5417304d26faSStefano Zampini       /* default */
5418304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5419e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
54202f37b69bSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->pA_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5421304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
54229577ea80SStefano Zampini       if (issbaij) {
54239577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
54249577ea80SStefano Zampini       } else {
5425304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
54269577ea80SStefano Zampini       }
5427399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure);CHKERRQ(ierr);
542892cccca0SStefano Zampini     }
542992cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(pcis->pA_II,((PetscObject)pcbddc->ksp_D)->prefix);CHKERRQ(ierr);
54302f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->pA_II);CHKERRQ(ierr);
5431304d26faSStefano Zampini     /* Allow user's customization */
543292cccca0SStefano Zampini     if (opts) {
5433304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
543492cccca0SStefano Zampini     }
543592cccca0SStefano Zampini     if (pcbddc->NullSpace_corr[0]) { /* approximate solver, propagate NearNullSpace */
543692cccca0SStefano Zampini       ierr = MatNullSpacePropagate_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II);CHKERRQ(ierr);
543792cccca0SStefano Zampini     }
543892cccca0SStefano Zampini     ierr = MatGetNearNullSpace(pcis->pA_II,&nnsp);CHKERRQ(ierr);
543992cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5440cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
544192cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5442cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5443cd18cfedSStefano Zampini       const PetscInt *idxs;
5444cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5445cd18cfedSStefano Zampini 
5446cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5447cd18cfedSStefano Zampini       ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5448cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5449cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5450cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5451cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5452cd18cfedSStefano Zampini         }
5453cd18cfedSStefano Zampini       }
5454cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5455cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5456cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5457cd18cfedSStefano Zampini     }
5458b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5459df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5460d62866d3SStefano Zampini 
5461df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5462d5574798SStefano Zampini     }
546392cccca0SStefano Zampini 
5464304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5465304d26faSStefano Zampini     if (!n_D) {
5466304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5467304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5468304d26faSStefano Zampini     }
5469304d26faSStefano Zampini     /* set ksp_D into pcis data */
5470304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
547192cccca0SStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5472304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5473684f6988SStefano Zampini   }
5474304d26faSStefano Zampini 
5475304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5476684f6988SStefano Zampini   A_RR = 0;
5477684f6988SStefano Zampini   if (neumann) {
5478d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
547904708bb6SStefano Zampini     PetscInt        ibs,mbs;
54800aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
548104708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
54820aa714b2SStefano Zampini 
54830aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
54840aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
54850aa714b2SStefano Zampini       IS iP;
54860aa714b2SStefano Zampini 
54870aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
54880aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
54890aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
54900aa714b2SStefano Zampini     }
5491f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
54928ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5493f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5494f4ddd8eeSStefano Zampini       PetscInt nn_R;
549581d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5496f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5497f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5498f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5499f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5500f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5501f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5502f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5503727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5504f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5505f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5506f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5507f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5508f4ddd8eeSStefano Zampini         }
5509f4ddd8eeSStefano Zampini       }
5510f4ddd8eeSStefano Zampini       /* last check */
5511d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5512f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5513f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5514f4ddd8eeSStefano Zampini       }
5515f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5516f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5517f4ddd8eeSStefano Zampini     }
5518a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5519af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5520af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
552104708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
552204708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
552304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
552404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
552504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5526af732b37SStefano Zampini       } else {
5527511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
55286816873aSStefano Zampini       }
552904708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
553004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
553104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
553204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
553304708bb6SStefano Zampini       } else {
5534511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
553504708bb6SStefano Zampini       }
553604708bb6SStefano Zampini     }
5537a00504b5SStefano Zampini     /* extract A_RR */
55380aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5539a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5540a00504b5SStefano Zampini 
5541a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
554216e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5543a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
554416e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
554516e386b8SStefano Zampini         } else {
55467dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5547a00504b5SStefano Zampini         }
5548a00504b5SStefano Zampini       } else {
5549a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5550a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5551a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5552a00504b5SStefano Zampini       }
5553a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
55547dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
555516e386b8SStefano Zampini     }
55563301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5557d1e098c7SStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
55586816873aSStefano Zampini     }
555992cccca0SStefano Zampini     opts = PETSC_FALSE;
5560f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
556192cccca0SStefano Zampini       opts = PETSC_TRUE;
5562304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5563304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5564304d26faSStefano Zampini       /* default */
5565304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5566e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5567304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
55689577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
55699577ea80SStefano Zampini       if (issbaij) {
55709577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
55719577ea80SStefano Zampini       } else {
5572304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
55739577ea80SStefano Zampini       }
5574399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure);CHKERRQ(ierr);
557592cccca0SStefano Zampini     }
55762f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
557792cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix);CHKERRQ(ierr);
557892cccca0SStefano Zampini     if (opts) { /* Allow user's customization once */
5579304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
558092cccca0SStefano Zampini     }
558192cccca0SStefano Zampini     if (pcbddc->NullSpace_corr[2]) { /* approximate solver, propagate NearNullSpace */
558292cccca0SStefano Zampini       ierr = MatNullSpacePropagate_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR);CHKERRQ(ierr);
558392cccca0SStefano Zampini     }
558492cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A_RR,&nnsp);CHKERRQ(ierr);
558592cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5586cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
558792cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5588cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5589cd18cfedSStefano Zampini       const PetscInt *idxs;
5590cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5591cd18cfedSStefano Zampini 
5592cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5593cd18cfedSStefano Zampini       ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5594cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5595cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5596cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5597cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5598cd18cfedSStefano Zampini         }
5599cd18cfedSStefano Zampini       }
5600cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5601cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5602cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5603cd18cfedSStefano Zampini     }
560492cccca0SStefano Zampini 
5605304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5606304d26faSStefano Zampini     if (!n_R) {
5607304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5608304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5609304d26faSStefano Zampini     }
5610df4d28bfSStefano Zampini     /* Reuse solver if it is present */
56110aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5612df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5613d62866d3SStefano Zampini 
5614df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5615d62866d3SStefano Zampini     }
5616684f6988SStefano Zampini   }
5617304d26faSStefano Zampini 
5618684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5619684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
56201575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5621684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5622684f6988SStefano Zampini   }
5623c7017625SStefano Zampini 
5624c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
5625c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5626c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5627c7017625SStefano Zampini   }
5628c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
5629c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5630c7017625SStefano Zampini   }
5631c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
5632c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5633c7017625SStefano Zampini   }
5634c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5635c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5636684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
56370fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
56380fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
56390fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
5640c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
56410fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
56420fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5643e604994aSStefano 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);
5644304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5645304d26faSStefano Zampini     }
5646684f6988SStefano Zampini     if (neumann) { /* Neumann */
56470fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
56480fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
56490fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5650c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
56510fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
56520fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5653e604994aSStefano 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);
5654304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5655304d26faSStefano Zampini     }
5656684f6988SStefano Zampini   }
56575cbda25cSStefano Zampini   /* free Neumann problem's matrix */
56585cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
565943371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5660304d26faSStefano Zampini   PetscFunctionReturn(0);
5661304d26faSStefano Zampini }
5662304d26faSStefano Zampini 
566380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5664674ae819SStefano Zampini {
5665674ae819SStefano Zampini   PetscErrorCode  ierr;
5666674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5667be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5668b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5669674ae819SStefano Zampini 
5670674ae819SStefano Zampini   PetscFunctionBegin;
5671b334f244SStefano Zampini   if (!reuse_solver) {
567280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
567320c7b377SStefano Zampini   }
567480677318SStefano Zampini   if (!pcbddc->switch_static) {
567580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
567680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
567780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
567820c7b377SStefano Zampini     }
5679b334f244SStefano Zampini     if (!reuse_solver) {
568080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
568180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
568220c7b377SStefano Zampini     } else {
5683df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5684be83ff47SStefano Zampini 
5685df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5686df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
568720c7b377SStefano Zampini     }
5688be83ff47SStefano Zampini   } else {
568980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
569080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
569180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
569280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
569380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
569480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
569580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
569680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
569780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5698674ae819SStefano Zampini     }
5699674ae819SStefano Zampini   }
5700b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
570180677318SStefano Zampini     if (applytranspose) {
570280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
570380677318SStefano Zampini     } else {
570480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
570580677318SStefano Zampini     }
5706c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R);CHKERRQ(ierr);
5707be83ff47SStefano Zampini   } else {
5708df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5709be83ff47SStefano Zampini 
5710be83ff47SStefano Zampini     if (applytranspose) {
5711df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5712be83ff47SStefano Zampini     } else {
5713df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5714be83ff47SStefano Zampini     }
5715be83ff47SStefano Zampini   }
571680677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
571780677318SStefano Zampini   if (!pcbddc->switch_static) {
5718b334f244SStefano Zampini     if (!reuse_solver) {
571980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
572080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5721be83ff47SStefano Zampini     } else {
5722df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5723be83ff47SStefano Zampini 
5724df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5725df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5726be83ff47SStefano Zampini     }
572780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
572880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
572980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
573080677318SStefano Zampini     }
573180677318SStefano Zampini   } else {
573280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
573380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
573480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
573580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
573680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
573780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
573880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
573980677318SStefano Zampini     }
574080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
574180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
574280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
574380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5744674ae819SStefano Zampini   }
5745674ae819SStefano Zampini   PetscFunctionReturn(0);
5746674ae819SStefano Zampini }
5747674ae819SStefano Zampini 
5748dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5749dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5750674ae819SStefano Zampini {
5751674ae819SStefano Zampini   PetscErrorCode ierr;
5752674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5753674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5754674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5755674ae819SStefano Zampini 
5756674ae819SStefano Zampini   PetscFunctionBegin;
5757dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
57584fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5759dc359a40SStefano Zampini     if (applytranspose) {
5760674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
57618eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5762dc359a40SStefano Zampini     } else {
5763674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5764674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
576515aaf578SStefano Zampini     }
57664fee134fSStefano Zampini   } else {
57674fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
57684fee134fSStefano Zampini   }
5769efc2fbd9SStefano Zampini 
5770efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
57714f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5772efc2fbd9SStefano Zampini     PetscScalar *array;
57734f1b2e48SStefano Zampini     PetscInt    j;
5774efc2fbd9SStefano Zampini 
5775efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
57764f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5777efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5778efc2fbd9SStefano Zampini   }
5779efc2fbd9SStefano Zampini 
578012edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
578112edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
578212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
578312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
578412edc857SStefano Zampini 
57859f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
578612edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
578751694757SStefano Zampini     Mat          coarse_mat;
5788964fefecSStefano Zampini     Vec          rhs,sol;
578951694757SStefano Zampini     MatNullSpace nullsp;
579027b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5791964fefecSStefano Zampini 
579227b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
579327b6a85dSStefano Zampini       PC        coarse_pc;
579427b6a85dSStefano Zampini 
579527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
579627b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
579727b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
579827b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
579927b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
580027b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
58013bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
580227b6a85dSStefano Zampini       }
580327b6a85dSStefano Zampini     }
5804964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5805964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
580651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
580712edc857SStefano Zampini     if (applytranspose) {
58089a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5809964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
5810c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
58119bfcb8eaSStefano Zampini       ierr = MatGetTransposeNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
58129bfcb8eaSStefano Zampini       if (nullsp) {
58139bfcb8eaSStefano Zampini         ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
58149bfcb8eaSStefano Zampini       }
58152701bc32SStefano Zampini     } else {
58169bfcb8eaSStefano Zampini       ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
58171f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
58182701bc32SStefano Zampini         PC        coarse_pc;
58192701bc32SStefano Zampini 
58209bfcb8eaSStefano Zampini         if (nullsp) {
58219bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
58229bfcb8eaSStefano Zampini         }
58232701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
58242701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
58253e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
58262701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
582712edc857SStefano Zampini       } else {
5828964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
5829c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
58309bfcb8eaSStefano Zampini         if (nullsp) {
58319bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
58329bfcb8eaSStefano Zampini         }
583312edc857SStefano Zampini       }
58342701bc32SStefano Zampini     }
58351d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
583627b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
583727b6a85dSStefano Zampini       PC        coarse_pc;
583827b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
583927b6a85dSStefano Zampini 
584027b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
584127b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
584227b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
58433bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
584427b6a85dSStefano Zampini     }
584512edc857SStefano Zampini   }
5846674ae819SStefano Zampini 
5847674ae819SStefano Zampini   /* Local solution on R nodes */
58484fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
584980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
58509f00e9b4SStefano Zampini   }
58519f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
58529f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
585312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5854674ae819SStefano Zampini 
58554fee134fSStefano Zampini   /* Sum contributions from the two levels */
58564fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5857dc359a40SStefano Zampini     if (applytranspose) {
5858dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5859dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5860dc359a40SStefano Zampini     } else {
5861674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
58628eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5863dc359a40SStefano Zampini     }
5864efc2fbd9SStefano Zampini     /* store p0 */
58654f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5866efc2fbd9SStefano Zampini       PetscScalar *array;
58674f1b2e48SStefano Zampini       PetscInt    j;
5868efc2fbd9SStefano Zampini 
5869efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
58704f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5871efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5872efc2fbd9SStefano Zampini     }
58734fee134fSStefano Zampini   } else { /* expand the coarse solution */
58744fee134fSStefano Zampini     if (applytranspose) {
58754fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
58764fee134fSStefano Zampini     } else {
58774fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
58784fee134fSStefano Zampini     }
58794fee134fSStefano Zampini   }
5880674ae819SStefano Zampini   PetscFunctionReturn(0);
5881674ae819SStefano Zampini }
5882674ae819SStefano Zampini 
588312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5884674ae819SStefano Zampini {
5885674ae819SStefano Zampini   PetscErrorCode ierr;
5886674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
588758da7f69SStefano Zampini   PetscScalar    *array;
588812edc857SStefano Zampini   Vec            from,to;
5889674ae819SStefano Zampini 
5890674ae819SStefano Zampini   PetscFunctionBegin;
589112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
589212edc857SStefano Zampini     from = pcbddc->coarse_vec;
589312edc857SStefano Zampini     to = pcbddc->vec1_P;
589412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
589512edc857SStefano Zampini       Vec tvec;
589658da7f69SStefano Zampini 
589758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
589858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
589912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
590058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
590158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
590258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
590312edc857SStefano Zampini     }
590412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
590512edc857SStefano Zampini     from = pcbddc->vec1_P;
590612edc857SStefano Zampini     to = pcbddc->coarse_vec;
590712edc857SStefano Zampini   }
590812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5909674ae819SStefano Zampini   PetscFunctionReturn(0);
5910674ae819SStefano Zampini }
5911674ae819SStefano Zampini 
591212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5913674ae819SStefano Zampini {
5914674ae819SStefano Zampini   PetscErrorCode ierr;
5915674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
591658da7f69SStefano Zampini   PetscScalar    *array;
591712edc857SStefano Zampini   Vec            from,to;
5918674ae819SStefano Zampini 
5919674ae819SStefano Zampini   PetscFunctionBegin;
592012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
592112edc857SStefano Zampini     from = pcbddc->coarse_vec;
592212edc857SStefano Zampini     to = pcbddc->vec1_P;
592312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
592412edc857SStefano Zampini     from = pcbddc->vec1_P;
592512edc857SStefano Zampini     to = pcbddc->coarse_vec;
592612edc857SStefano Zampini   }
592712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
592812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
592912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
593012edc857SStefano Zampini       Vec tvec;
593158da7f69SStefano Zampini 
593212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
593358da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
593458da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
593558da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
593658da7f69SStefano Zampini     }
593758da7f69SStefano Zampini   } else {
593858da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
593958da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
594012edc857SStefano Zampini     }
594112edc857SStefano Zampini   }
5942674ae819SStefano Zampini   PetscFunctionReturn(0);
5943674ae819SStefano Zampini }
5944674ae819SStefano Zampini 
5945984c4197SStefano Zampini /* uncomment for testing purposes */
5946984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5947674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5948674ae819SStefano Zampini {
5949674ae819SStefano Zampini   PetscErrorCode    ierr;
5950674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5951674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5952674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5953984c4197SStefano Zampini   /* one and zero */
5954984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5955984c4197SStefano Zampini   /* space to store constraints and their local indices */
59569162d606SStefano Zampini   PetscScalar       *constraints_data;
59579162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
59589162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
59599162d606SStefano Zampini   PetscInt          *constraints_n;
5960984c4197SStefano Zampini   /* iterators */
5961b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5962984c4197SStefano Zampini   /* BLAS integers */
5963e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5964e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5965c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5966727cdba6SStefano Zampini   /* reuse */
59670e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
59680e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5969984c4197SStefano Zampini   /* change of basis */
5970b3d85658SStefano Zampini   PetscBool         qr_needed;
59719162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5972984c4197SStefano Zampini   /* auxiliary stuff */
597364efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
59748a0068c3SStefano Zampini   PetscInt          ncc;
5975984c4197SStefano Zampini   /* some quantities */
597645a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5977a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
597857715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
5979984c4197SStefano Zampini 
5980674ae819SStefano Zampini   PetscFunctionBegin;
598157715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
59828e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
59838e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
59848e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
598516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5986088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5987088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
59880e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
59890e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
5990*580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc);CHKERRQ(ierr);
5991*580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc);CHKERRQ(ierr);
59920e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5993088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5994cf5a6209SStefano Zampini 
5995cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
59969162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5997cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5998cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5999cf5a6209SStefano Zampini     Vec          *localnearnullsp;
6000cf5a6209SStefano Zampini     PetscScalar  *array;
6001cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
6002cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
6003674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
6004b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
6005674ae819SStefano Zampini     PetscScalar  *work;
6006674ae819SStefano Zampini     PetscReal    *singular_vals;
6007674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6008674ae819SStefano Zampini     PetscReal    *rwork;
6009674ae819SStefano Zampini #endif
6010674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6011674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
6012674ae819SStefano Zampini #else
6013964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
6014964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
6015674ae819SStefano Zampini #endif
6016674ae819SStefano Zampini 
6017674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
6018d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
6019e4d548c7SStefano Zampini     /* print some info */
60205c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
6021e4d548c7SStefano Zampini       PetscInt nv;
6022e4d548c7SStefano Zampini 
6023c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6024e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
6025e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6026e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
60276080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
60286080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
60296080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
6030e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6031e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6032e4d548c7SStefano Zampini     }
6033e4d548c7SStefano Zampini 
6034d06fc5fdSStefano Zampini     /* free unneeded index sets */
6035d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
6036d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
6037674ae819SStefano Zampini     }
6038d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
6039d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
6040d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6041d06fc5fdSStefano Zampini       }
6042d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6043d06fc5fdSStefano Zampini       n_ISForEdges = 0;
6044d06fc5fdSStefano Zampini     }
6045d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
6046d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
6047d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6048d06fc5fdSStefano Zampini       }
6049d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6050d06fc5fdSStefano Zampini       n_ISForFaces = 0;
6051d06fc5fdSStefano Zampini     }
605270022509SStefano Zampini 
6053674ae819SStefano Zampini     /* check if near null space is attached to global mat */
6054674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
6055674ae819SStefano Zampini     if (nearnullsp) {
6056674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
6057f4ddd8eeSStefano Zampini       /* remove any stored info */
6058f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
6059f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6060f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
6061f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
6062f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
6063473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6064f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
6065f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
6066f4ddd8eeSStefano Zampini       }
6067984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
6068984c4197SStefano Zampini       nnsp_size = 0;
6069674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
6070674ae819SStefano Zampini     }
6071984c4197SStefano Zampini     /* get max number of constraints on a single cc */
6072984c4197SStefano Zampini     max_constraints = nnsp_size;
6073984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
6074984c4197SStefano Zampini 
6075674ae819SStefano Zampini     /*
6076674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
60779162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
60789162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
60799162d606SStefano Zampini          There can be multiple constraints per connected component
6080674ae819SStefano Zampini                                                                                                                                                            */
6081674ae819SStefano Zampini     n_vertices = 0;
6082674ae819SStefano Zampini     if (ISForVertices) {
6083674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
6084674ae819SStefano Zampini     }
60859162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
60869162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
60879162d606SStefano Zampini 
60889162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
60899162d606SStefano Zampini     total_counts *= max_constraints;
6090674ae819SStefano Zampini     total_counts += n_vertices;
60914641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
60929162d606SStefano Zampini 
6093674ae819SStefano Zampini     total_counts = 0;
6094674ae819SStefano Zampini     max_size_of_constraint = 0;
6095674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
60969162d606SStefano Zampini       IS used_is;
6097674ae819SStefano Zampini       if (i<n_ISForEdges) {
60989162d606SStefano Zampini         used_is = ISForEdges[i];
6099674ae819SStefano Zampini       } else {
61009162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
6101674ae819SStefano Zampini       }
61029162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
6103674ae819SStefano Zampini       total_counts += j;
6104674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
6105674ae819SStefano Zampini     }
61069162d606SStefano 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);
61079162d606SStefano Zampini 
6108984c4197SStefano Zampini     /* get local part of global near null space vectors */
6109785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
6110984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6111984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
6112e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6113e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6114984c4197SStefano Zampini     }
6115674ae819SStefano Zampini 
6116242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
6117242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
6118a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
6119242a89d7SStefano Zampini 
6120984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
6121a773dcb8SStefano Zampini     if (!skip_lapack) {
6122674ae819SStefano Zampini       PetscScalar temp_work;
6123911cabfeSStefano Zampini 
6124674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6125984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
6126785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
6127785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
6128785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
6129674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6130785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
6131674ae819SStefano Zampini #endif
6132674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
6133c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
6134c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
6135674ae819SStefano Zampini       lwork = -1;
6136674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6137674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6138c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6139674ae819SStefano Zampini #else
6140c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6141674ae819SStefano Zampini #endif
6142674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
6143984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
6144674ae819SStefano Zampini #else /* on missing GESVD */
6145674ae819SStefano Zampini       /* SVD */
6146674ae819SStefano Zampini       PetscInt max_n,min_n;
6147674ae819SStefano Zampini       max_n = max_size_of_constraint;
6148984c4197SStefano Zampini       min_n = max_constraints;
6149984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
6150674ae819SStefano Zampini         min_n = max_size_of_constraint;
6151984c4197SStefano Zampini         max_n = max_constraints;
6152674ae819SStefano Zampini       }
6153785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
6154674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6155785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
6156674ae819SStefano Zampini #endif
6157674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
6158674ae819SStefano Zampini       lwork = -1;
6159e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
6160e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
6161b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
6162674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6163674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
61649162d606SStefano 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));
6165674ae819SStefano Zampini #else
61669162d606SStefano 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));
6167674ae819SStefano Zampini #endif
6168674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
6169984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
6170984c4197SStefano Zampini #endif /* on missing GESVD */
6171674ae819SStefano Zampini       /* Allocate optimal workspace */
6172674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
6173854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
6174674ae819SStefano Zampini     }
6175674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6176674ae819SStefano Zampini     total_counts = 0;
61779162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
61789162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6179674ae819SStefano Zampini     /* vertices */
61809162d606SStefano Zampini     if (n_vertices) {
6181674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6182*580bdb30SBarry Smith       ierr = PetscArraycpy(constraints_idxs,is_indices,n_vertices);CHKERRQ(ierr);
6183674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
61849162d606SStefano Zampini         constraints_n[total_counts] = 1;
61859162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
61869162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
61879162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6188674ae819SStefano Zampini         total_counts++;
6189674ae819SStefano Zampini       }
6190674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6191674ae819SStefano Zampini       n_vertices = total_counts;
6192674ae819SStefano Zampini     }
6193984c4197SStefano Zampini 
6194674ae819SStefano Zampini     /* edges and faces */
61959162d606SStefano Zampini     total_counts_cc = total_counts;
6196911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
61979162d606SStefano Zampini       IS        used_is;
61989162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
61999162d606SStefano Zampini 
6200911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
62019162d606SStefano Zampini         used_is = ISForEdges[ncc];
6202984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6203674ae819SStefano Zampini       } else {
62049162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6205984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6206674ae819SStefano Zampini       }
6207674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
62089162d606SStefano Zampini 
62099162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
62109162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6211984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6212984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6213674ae819SStefano Zampini       if (nnsp_has_cnst) {
62145b08dc53SStefano Zampini         PetscScalar quad_value;
62159162d606SStefano Zampini 
6216*580bdb30SBarry Smith         ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
62179162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
62189162d606SStefano Zampini 
6219a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6220674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6221a773dcb8SStefano Zampini         } else {
6222a773dcb8SStefano Zampini           quad_value = 1.0;
6223a773dcb8SStefano Zampini         }
6224674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
62259162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6226674ae819SStefano Zampini         }
62279162d606SStefano Zampini         temp_constraints++;
6228674ae819SStefano Zampini         total_counts++;
6229674ae819SStefano Zampini       }
6230674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6231984c4197SStefano Zampini         PetscReal real_value;
62329162d606SStefano Zampini         PetscScalar *ptr_to_data;
62339162d606SStefano Zampini 
6234984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
62359162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6236674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
62379162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6238674ae819SStefano Zampini         }
6239984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
6240984c4197SStefano Zampini         /* check if array is null on the connected component */
6241e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
62429162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
624357715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6244674ae819SStefano Zampini           temp_constraints++;
6245674ae819SStefano Zampini           total_counts++;
62469162d606SStefano Zampini           if (!idxs_copied) {
6247*580bdb30SBarry Smith             ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
62489162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6249674ae819SStefano Zampini           }
6250674ae819SStefano Zampini         }
62519162d606SStefano Zampini       }
62529162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
625345a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6254eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6255a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
62569162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
62579162d606SStefano Zampini 
62589162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6259a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
62609162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6261a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
62629162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6263a773dcb8SStefano Zampini         } else { /* perform SVD */
62649162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6265674ae819SStefano Zampini 
6266674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6267984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6268984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6269984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6270984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
6271984c4197SStefano Zampini                 from that computed using LAPACKgesvd
6272984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
6273984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
6274*580bdb30SBarry Smith           ierr = PetscArrayzero(correlation_mat,temp_constraints*temp_constraints);CHKERRQ(ierr);
6275674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
6276e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6277984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6278674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
6279674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
62809162d606SStefano 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));
6281674ae819SStefano Zampini             }
6282674ae819SStefano Zampini           }
6283e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
6284e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6285e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6286674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6287c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6288674ae819SStefano Zampini #else
6289c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6290674ae819SStefano Zampini #endif
6291674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6292984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6293984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6294674ae819SStefano Zampini           j = 0;
629587b3baaaSStefano Zampini           while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6296674ae819SStefano Zampini           total_counts = total_counts-j;
629745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
6298e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
6299c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6300c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6301c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6302c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6303c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6304c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6305674ae819SStefano Zampini           if (j<temp_constraints) {
6306984c4197SStefano Zampini             PetscInt ii;
6307984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6308674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63099162d606SStefano 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));
6310674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6311984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
6312674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
63139162d606SStefano 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];
6314674ae819SStefano Zampini               }
6315674ae819SStefano Zampini             }
6316674ae819SStefano Zampini           }
6317674ae819SStefano Zampini #else  /* on missing GESVD */
6318e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6319e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6320b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6321674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6322674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
63239162d606SStefano 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));
6324674ae819SStefano Zampini #else
63259162d606SStefano 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));
6326674ae819SStefano Zampini #endif
6327984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6328674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6329984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6330e310c8b4SStefano Zampini           k = temp_constraints;
6331e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
6332674ae819SStefano Zampini           j = 0;
633387b3baaaSStefano Zampini           while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
633445a1bb75SStefano Zampini           valid_constraints = k-j;
6335911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
6336984c4197SStefano Zampini #endif /* on missing GESVD */
6337674ae819SStefano Zampini         }
6338a773dcb8SStefano Zampini       }
63399162d606SStefano Zampini       /* update pointers information */
63409162d606SStefano Zampini       if (valid_constraints) {
63419162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
63429162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
63439162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
63449162d606SStefano Zampini         /* set change_of_basis flag */
634545a1bb75SStefano Zampini         if (boolforchange) {
6346b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
63479162d606SStefano Zampini         }
6348b3d85658SStefano Zampini         total_counts_cc++;
634945a1bb75SStefano Zampini       }
635045a1bb75SStefano Zampini     }
6351984c4197SStefano Zampini     /* free workspace */
63528f1c130eSStefano Zampini     if (!skip_lapack) {
6353984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6354984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6355984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6356984c4197SStefano Zampini #endif
6357984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6358984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6359984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6360984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6361984c4197SStefano Zampini #endif
6362984c4197SStefano Zampini     }
6363984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6364984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6365984c4197SStefano Zampini     }
6366984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6367cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6368cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6369cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6370cf5a6209SStefano Zampini     }
6371cf5a6209SStefano Zampini     if (n_ISForFaces) {
6372cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6373cf5a6209SStefano Zampini     }
6374cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6375cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6376cf5a6209SStefano Zampini     }
6377cf5a6209SStefano Zampini     if (n_ISForEdges) {
6378cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6379cf5a6209SStefano Zampini     }
6380cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
638108122e43SStefano Zampini   } else {
638208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6383984c4197SStefano Zampini 
638408122e43SStefano Zampini     total_counts = 0;
638508122e43SStefano Zampini     n_vertices = 0;
6386d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6387d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
638808122e43SStefano Zampini     }
638908122e43SStefano Zampini     max_constraints = 0;
63909162d606SStefano Zampini     total_counts_cc = 0;
639108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
639208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
63939162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
639408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
639508122e43SStefano Zampini     }
63969162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
63979162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
63989162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
63999162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
640074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
64019162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
64029162d606SStefano Zampini     total_counts_cc = 0;
64039162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
64049162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
64059162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
640608122e43SStefano Zampini       }
640708122e43SStefano Zampini     }
640808122e43SStefano Zampini 
64098bec7fa6SStefano Zampini     max_size_of_constraint = 0;
64109162d606SStefano 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]);
64119162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
641208122e43SStefano Zampini     /* Change of basis */
6413b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
641408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
641508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
641608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6417b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
641808122e43SStefano Zampini         }
641908122e43SStefano Zampini       }
642008122e43SStefano Zampini     }
642108122e43SStefano Zampini   }
6422984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
64234f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
642408122e43SStefano Zampini 
64259162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
64269162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
64276080607fSStefano 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);
6428674ae819SStefano Zampini 
6429674ae819SStefano Zampini   /* Create constraint matrix */
6430674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
643116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6432984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6433984c4197SStefano Zampini 
6434984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6435a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
64365a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
643774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6438984c4197SStefano Zampini   total_primal_vertices=0;
6439b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
64409162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
64419162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
644272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
64439162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6444b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
644564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
64469162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
64479162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6448a717540cSStefano Zampini       }
6449b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
645091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6451a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6452a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6453a717540cSStefano Zampini       }
6454fa434743SStefano Zampini     } else {
6455b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6456fa434743SStefano Zampini     }
6457a717540cSStefano Zampini   }
6458b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6459b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6460674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
646170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
64624f1b2e48SStefano 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);
6463*580bdb30SBarry Smith   ierr = PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices);CHKERRQ(ierr);
64640e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6465984c4197SStefano Zampini 
6466984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
646774d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6468785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6469984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
647074d5cdf7SStefano Zampini 
6471984c4197SStefano Zampini   j = total_primal_vertices;
647274d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6473b3d85658SStefano Zampini   cum = total_primal_vertices;
64749162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
64754641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6476b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6477b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6478b3d85658SStefano Zampini       cum++;
64799162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
648074d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
648174d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
648274d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
648374d5cdf7SStefano Zampini       }
64849162d606SStefano Zampini       j += constraints_n[i];
6485674ae819SStefano Zampini     }
6486674ae819SStefano Zampini   }
6487674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6488e1b21442SStefano Zampini   ierr = MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6489674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6490088faed8SStefano Zampini 
6491674ae819SStefano Zampini   /* set values in constraint matrix */
6492984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
64930e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6494674ae819SStefano Zampini   }
6495984c4197SStefano Zampini   total_counts = total_primal_vertices;
64969162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
64974641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
64989162d606SStefano Zampini       PetscInt *cols;
64999162d606SStefano Zampini 
65009162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
65019162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
65029162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65039162d606SStefano Zampini         PetscInt    row = total_counts+k;
65049162d606SStefano Zampini         PetscScalar *vals;
65059162d606SStefano Zampini 
65069162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
65079162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
65089162d606SStefano Zampini       }
65099162d606SStefano Zampini       total_counts += constraints_n[i];
6510674ae819SStefano Zampini     }
6511674ae819SStefano Zampini   }
6512674ae819SStefano Zampini   /* assembling */
6513674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6514674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65153272d46bSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,NULL,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6516088faed8SStefano Zampini 
6517674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6518674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6519026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6520984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6521984c4197SStefano Zampini     /* working stuff for GEQRF */
65225a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6523984c4197SStefano Zampini     PetscBLASInt lqr_work;
6524984c4197SStefano Zampini     /* working stuff for UNGQR */
65255a52fde0SStefano Zampini     PetscScalar  *gqr_work = NULL,lgqr_work_t;
6526984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6527984c4197SStefano Zampini     /* working stuff for TRTRS */
65285a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
65293f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6530984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6531984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6532984c4197SStefano Zampini     PetscScalar  *start_vals;
6533984c4197SStefano Zampini     /* working stuff for values insertion */
65344641a718SStefano Zampini     PetscBT      is_primal;
653564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6536906d46d4SStefano Zampini     /* matrix sizes */
6537906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6538906d46d4SStefano Zampini     /* temporary change of basis */
6539906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6540cf5a6209SStefano Zampini     /* extra space for debugging */
65415a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6542984c4197SStefano Zampini 
6543906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6544906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
654516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6546bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6547906d46d4SStefano Zampini     /* nonzeros for local mat */
6548bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
65491dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6550bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
65511dd7afcfSStefano Zampini     } else {
65521dd7afcfSStefano Zampini       const PetscInt *ii;
65531dd7afcfSStefano Zampini       PetscInt       n;
65541dd7afcfSStefano Zampini       PetscBool      flg_row;
65551dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
65561dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
65571dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
65581dd7afcfSStefano Zampini     }
65599162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6560a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
65619162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6562a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
65639162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6564a717540cSStefano Zampini         } else {
65659162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
65669162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6567a717540cSStefano Zampini         }
6568a717540cSStefano Zampini       }
6569a717540cSStefano Zampini     }
6570906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6571e1b21442SStefano Zampini     ierr = MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6572bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
65731dd7afcfSStefano Zampini     /* Set interior change in the matrix */
65741dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6575bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6576906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6577a717540cSStefano Zampini       }
65781dd7afcfSStefano Zampini     } else {
65791dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
65801dd7afcfSStefano Zampini       PetscScalar    *aa;
65811dd7afcfSStefano Zampini       PetscInt       n;
65821dd7afcfSStefano Zampini       PetscBool      flg_row;
65831dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
65841dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
65851dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
65861dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
65871dd7afcfSStefano Zampini       }
65881dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
65891dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
65901dd7afcfSStefano Zampini     }
6591a717540cSStefano Zampini 
6592a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6593a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6594a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6595a717540cSStefano Zampini     }
6596a717540cSStefano Zampini 
6597a717540cSStefano Zampini 
6598a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6599a717540cSStefano Zampini     /*
6600a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6601a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6602a717540cSStefano Zampini 
6603a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6604a717540cSStefano Zampini 
6605a6b551f4SStefano 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)
6606a6b551f4SStefano Zampini 
6607a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6608a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6609a717540cSStefano Zampini             |              ...                        |
6610a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6611a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6612a717540cSStefano Zampini 
6613a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6614a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6615a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6616a6b551f4SStefano Zampini 
6617a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6618a717540cSStefano Zampini     */
66195a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6620984c4197SStefano Zampini       /* space to store Q */
6621854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
66224e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
66234e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6624984c4197SStefano Zampini       /* first we issue queries for optimal work */
66253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
66263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
66273f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6628984c4197SStefano Zampini       lqr_work = -1;
66293f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6630984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6631984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6632785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6633984c4197SStefano Zampini       lgqr_work = -1;
66343f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
66353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
66363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
66373f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
66383f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6639c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6640c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6641984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6642785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6643984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6644785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6645a717540cSStefano Zampini       /* allocating workspace for check */
6646a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6647cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6648a717540cSStefano Zampini       }
6649a717540cSStefano Zampini     }
6650984c4197SStefano Zampini     /* array to store whether a node is primal or not */
66514641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6652473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
66530e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
66546080607fSStefano 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);
665539e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
665639e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
665739e2fb2aSStefano Zampini     }
665839e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6659984c4197SStefano Zampini 
6660a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
66619162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
66629162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
66634641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6664984c4197SStefano Zampini         /* get constraint info */
66659162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6666984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6667984c4197SStefano Zampini 
6668984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
66696080607fSStefano 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);
6670674ae819SStefano Zampini         }
6671984c4197SStefano Zampini 
6672fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6673a717540cSStefano Zampini 
6674a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6675a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
6676*580bdb30SBarry Smith             ierr = PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6677a717540cSStefano Zampini           }
6678984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
6679*580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6680984c4197SStefano Zampini 
6681984c4197SStefano Zampini           /* compute QR decomposition of constraints */
66823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
66833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
66843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6685674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
66863f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6687984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6688674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6689984c4197SStefano Zampini 
6690984c4197SStefano Zampini           /* explictly compute R^-T */
6691*580bdb30SBarry Smith           ierr = PetscArrayzero(trs_rhs,primal_dofs*primal_dofs);CHKERRQ(ierr);
6692984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
66933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
66943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
66953f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
66963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6697984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
66983f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6699984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6700984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6701984c4197SStefano Zampini 
6702a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
67033f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67043f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
67053f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
67063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6707984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6708c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6709c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6710984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6711984c4197SStefano Zampini 
6712984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6713984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6714984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
67153f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67163f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
67173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
67183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
67193f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
67203f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6721984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
67229162d606SStefano 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));
6723984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6724*580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6725984c4197SStefano Zampini 
6726984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
67279162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6728984c4197SStefano Zampini           /* insert cols for primal dofs */
6729984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6730984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
67319162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6732906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6733984c4197SStefano Zampini           }
6734984c4197SStefano Zampini           /* insert cols for dual dofs */
6735984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
67369162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6737984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
67389162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6739906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6740984c4197SStefano Zampini               j++;
6741674ae819SStefano Zampini             }
6742674ae819SStefano Zampini           }
6743984c4197SStefano Zampini 
6744984c4197SStefano Zampini           /* check change of basis */
6745984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6746984c4197SStefano Zampini             PetscInt   ii,jj;
6747984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6748c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6749c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6750c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6751c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6752c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6753c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6754984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6755cf5a6209SStefano 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));
6756984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6757984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6758984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6759cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6760c068d9bbSLisandro 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;
6761674ae819SStefano Zampini               }
6762674ae819SStefano Zampini             }
6763984c4197SStefano Zampini             if (!valid_qr) {
676422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6765984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6766984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6767cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
67686080607fSStefano 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);
6769674ae819SStefano Zampini                   }
6770c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
67716080607fSStefano 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);
6772984c4197SStefano Zampini                   }
6773984c4197SStefano Zampini                 }
6774984c4197SStefano Zampini               }
6775674ae819SStefano Zampini             } else {
677622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6777674ae819SStefano Zampini             }
6778674ae819SStefano Zampini           }
6779a717540cSStefano Zampini         } else { /* simple transformation block */
6780a717540cSStefano Zampini           PetscInt    row,col;
6781a6b551f4SStefano Zampini           PetscScalar val,norm;
6782a6b551f4SStefano Zampini 
6783a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
67849162d606SStefano 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));
6785a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
67869162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
67879162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6788bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
67899162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6790906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
67919162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6792a717540cSStefano Zampini             } else {
6793a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
67949162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6795a717540cSStefano Zampini                 if (row != col) {
67969162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6797a717540cSStefano Zampini                 } else {
67989162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6799a717540cSStefano Zampini                 }
6800906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6801a717540cSStefano Zampini               }
6802a717540cSStefano Zampini             }
6803a717540cSStefano Zampini           }
680498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
680522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6806a717540cSStefano Zampini           }
6807674ae819SStefano Zampini         }
6808984c4197SStefano Zampini       } else {
6809984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
68106080607fSStefano 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);
6811674ae819SStefano Zampini         }
6812674ae819SStefano Zampini       }
6813674ae819SStefano Zampini     }
6814a717540cSStefano Zampini 
6815a717540cSStefano Zampini     /* free workspace */
6816a717540cSStefano Zampini     if (qr_needed) {
6817984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6818cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6819984c4197SStefano Zampini       }
6820984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6821984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6822984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6823984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6824984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6825674ae819SStefano Zampini     }
6826a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6827906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6828906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6829906d46d4SStefano Zampini 
6830906d46d4SStefano Zampini     /* assembling of global change of variable */
683188c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6832bbb9e6c6SStefano Zampini       Mat      tmat;
683316f15bc4SStefano Zampini       PetscInt bs;
683416f15bc4SStefano Zampini 
6835906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6836906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6837bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6838bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6839487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6840487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6841bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6842bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
684316f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
684416f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6845906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6846bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6847487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6848bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6849bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6850bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6851e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6852e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6853bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6854bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
685588c03ad3SStefano Zampini 
6856906d46d4SStefano Zampini       /* check */
6857906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6858906d46d4SStefano Zampini         PetscReal error;
6859906d46d4SStefano Zampini         Vec       x,x_change;
6860906d46d4SStefano Zampini 
6861906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6862906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6863906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6864906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6865e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6866e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6867bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6868e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6869e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6870906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6871906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6872906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6873637e8532SStefano Zampini         if (error > PETSC_SMALL) {
68746080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
6875637e8532SStefano Zampini         }
6876906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6877906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6878906d46d4SStefano Zampini       }
6879b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6880b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6881b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6882bf3a8328SStefano Zampini 
688313903a91SSatish 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");
6884b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6885ac632422SStefano Zampini           Mat                    S_new,tmat;
6886bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6887bbb9e6c6SStefano Zampini 
6888bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
68897dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6890bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6891bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6892bf3a8328SStefano Zampini             IS                     is_V;
6893b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6894b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6895b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6896b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6897b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6898bf3a8328SStefano Zampini           }
6899bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6900ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6901b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6902ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6903bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6904bf3a8328SStefano Zampini             const PetscScalar *array;
6905bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6906bf3a8328SStefano Zampini             PetscInt          i,n_V;
6907bf3a8328SStefano Zampini 
6908b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6909b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6910b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6911b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6912b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6913b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6914b087196eSStefano Zampini               PetscScalar val;
6915b087196eSStefano Zampini               PetscInt    idx;
6916b087196eSStefano Zampini 
6917b087196eSStefano Zampini               idx = idxs_V[i];
6918b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6919b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6920b087196eSStefano Zampini             }
6921b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6922b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6923bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6924bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6925bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6926bf3a8328SStefano Zampini           }
6927ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6928ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6929ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6930ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6931b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6932ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6933bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6934b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6935bf3a8328SStefano Zampini             }
6936ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6937ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6938ac632422SStefano Zampini           }
6939b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
694088c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6941b96c3477SStefano Zampini         }
6942c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6943b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6944c9db6a07SStefano Zampini           PetscInt i;
6945c9db6a07SStefano Zampini 
6946c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6947c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6948c9db6a07SStefano Zampini           }
6949c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6950c9db6a07SStefano Zampini         }
6951b96c3477SStefano Zampini       }
695216909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
695316909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
695416909a7fSStefano Zampini       } else {
6955906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
695616909a7fSStefano Zampini       }
69571dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
695827b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
695972b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
696072b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
696172b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
696272b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
696372b8c272SStefano Zampini     }
69641dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
696527b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6966b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6967b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6968906d46d4SStefano Zampini     } else {
69691dd7afcfSStefano Zampini       Mat benign_global = NULL;
697027b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
69711dd7afcfSStefano Zampini         Mat M;
69721dd7afcfSStefano Zampini 
69739e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
69749e9b7b1fSStefano Zampini         ierr = VecCopy(matis->counter,pcis->vec1_N);CHKERRQ(ierr);
69759e9b7b1fSStefano Zampini         ierr = VecReciprocal(pcis->vec1_N);CHKERRQ(ierr);
69769e9b7b1fSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global);CHKERRQ(ierr);
69779e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
69781dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
69791dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
6980906d46d4SStefano Zampini         } else {
69819e9b7b1fSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M);CHKERRQ(ierr);
69829e9b7b1fSStefano Zampini           ierr = MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES);CHKERRQ(ierr);
6983906d46d4SStefano Zampini         }
69849e9b7b1fSStefano Zampini         ierr = MatISSetLocalMat(benign_global,M);CHKERRQ(ierr);
69859e9b7b1fSStefano Zampini         ierr = MatDestroy(&M);CHKERRQ(ierr);
69869e9b7b1fSStefano Zampini         ierr = MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69879e9b7b1fSStefano Zampini         ierr = MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69881dd7afcfSStefano Zampini       }
69891dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
69901dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
69911dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
699227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
69931dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
69941dd7afcfSStefano Zampini       }
69951dd7afcfSStefano Zampini     }
699616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
699716909a7fSStefano Zampini       IS             is_global;
699816909a7fSStefano Zampini       const PetscInt *gidxs;
699916909a7fSStefano Zampini 
700016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
700116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
700216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
70037dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
700416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
700516909a7fSStefano Zampini     }
70061dd7afcfSStefano Zampini   }
70071dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
70081dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
7009b9b85e73SStefano Zampini   }
7010a717540cSStefano Zampini 
701172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
70124f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
70134f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
70144f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
70154f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
7016019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
7017019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
7018019a44ceSStefano Zampini       pcbddc->local_primal_size++;
7019019a44ceSStefano Zampini     }
7020019a44ceSStefano Zampini 
7021019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
7022727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
7023727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
7024*580bdb30SBarry Smith       ierr = PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7025c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
70260e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
7027*580bdb30SBarry Smith         ierr = PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7028727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
7029727cdba6SStefano Zampini       }
70300e6343abSStefano Zampini     }
7031727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
7032b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
703372b8c272SStefano Zampini   }
703472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
7035727cdba6SStefano Zampini 
7036a717540cSStefano Zampini   /* flush dbg viewer */
7037b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
7038b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7039b8ffe317SStefano Zampini   }
7040a717540cSStefano Zampini 
7041e310c8b4SStefano Zampini   /* free workspace */
7042a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
70434641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
704408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
70459162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
70469162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
704708122e43SStefano Zampini   } else {
70489162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
70499162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
70509162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
705108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
705208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
70539162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
70549162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
705508122e43SStefano Zampini   }
7056674ae819SStefano Zampini   PetscFunctionReturn(0);
7057674ae819SStefano Zampini }
705804a6f24aSStefano Zampini /* #undef PETSC_MISSING_LAPACK_GESVD */
7059674ae819SStefano Zampini 
7060674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
7061674ae819SStefano Zampini {
706271582508SStefano Zampini   ISLocalToGlobalMapping map;
7063674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7064674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
706566da6bd7Sstefano_zampini   PetscInt               i,N;
706666da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
706766da6bd7Sstefano_zampini   PetscErrorCode         ierr;
7068674ae819SStefano Zampini 
7069674ae819SStefano Zampini   PetscFunctionBegin;
70708af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
7071b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
70728e61c736SStefano Zampini     /* Reset previously computed graph */
70738e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
7074674ae819SStefano Zampini     /* Init local Graph struct */
70757fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
707671582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
7077be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
7078674ae819SStefano Zampini 
70797a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
70807a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
70817a0e7b2cSstefano_zampini     }
7082575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
70836080607fSStefano 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);
70849577ea80SStefano Zampini 
7085674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
708666da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
70874d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
70884d379d7bSStefano Zampini       PetscInt  nvtxs;
7089e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
7090674ae819SStefano Zampini 
70912fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
70922fffb893SStefano Zampini       if (flg_row) {
70934d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
7094b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
70952fffb893SStefano Zampini       }
70962fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
709766da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
7098674ae819SStefano Zampini     }
70999b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
71009b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7101674ae819SStefano Zampini     }
7102674ae819SStefano Zampini 
7103ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
7104ab8c8b98SStefano Zampini       PetscReal    *lcoords;
7105ab8c8b98SStefano Zampini       PetscInt     n;
7106ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
7107ab8c8b98SStefano Zampini 
71084f819b78SStefano Zampini       /* TODO: support for blocked */
7109ab8c8b98SStefano 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);
7110ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
7111ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
7112ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
7113ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
7114ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
7115ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
7116ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
7117ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
7118ab8c8b98SStefano Zampini 
7119ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
7120ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
7121ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
7122ab8c8b98SStefano Zampini     }
7123ab8c8b98SStefano 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);
71241c7a958bSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && !pcbddc->corner_selected);
7125ab8c8b98SStefano Zampini 
7126674ae819SStefano Zampini     /* Setup of Graph */
71274b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
712814f95afaSStefano 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);
7129674ae819SStefano Zampini 
71304f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
71314f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
713220c3699dSStefano Zampini       PetscInt *local_subs,n,totn;
71334f1b2e48SStefano Zampini 
713420c3699dSStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
713520c3699dSStefano Zampini       ierr = PetscMalloc1(n,&local_subs);CHKERRQ(ierr);
713620c3699dSStefano Zampini       for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs;
71374f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
71384f1b2e48SStefano Zampini         const PetscInt *idxs;
71394f1b2e48SStefano Zampini         PetscInt       nl,j;
71404f1b2e48SStefano Zampini 
71414f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
71424f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
714371582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
71444f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
71454f1b2e48SStefano Zampini       }
714620c3699dSStefano Zampini       for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]);
714720c3699dSStefano Zampini       pcbddc->mat_graph->n_local_subs = totn + 1;
71484f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
71494f1b2e48SStefano Zampini     }
71508af8fcf9SStefano Zampini   }
71514f1b2e48SStefano Zampini 
7152cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7153674ae819SStefano Zampini     /* Graph's connected components analysis */
7154674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
715571582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
71564f819b78SStefano Zampini     pcbddc->corner_selected = pcbddc->corner_selection;
71578af8fcf9SStefano Zampini   }
715866da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7159674ae819SStefano Zampini   PetscFunctionReturn(0);
7160674ae819SStefano Zampini }
7161674ae819SStefano Zampini 
71629a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
71639a7d3425SStefano Zampini {
71649a7d3425SStefano Zampini   PetscInt       i,j;
71659a7d3425SStefano Zampini   PetscScalar    *alphas;
716692cccca0SStefano Zampini   PetscReal      norm;
71679a7d3425SStefano Zampini   PetscErrorCode ierr;
71689a7d3425SStefano Zampini 
71699a7d3425SStefano Zampini   PetscFunctionBegin;
71708c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
7171785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
717292cccca0SStefano Zampini   ierr = VecNormalize(vecs[0],&norm);CHKERRQ(ierr);
717392cccca0SStefano Zampini   if (norm < PETSC_SMALL) {
717492cccca0SStefano Zampini     ierr = VecSet(vecs[0],0.0);CHKERRQ(ierr);
717592cccca0SStefano Zampini   }
71768c0031efSStefano Zampini   for (i=1;i<n;i++) {
71778c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
71788c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
71798c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
718092cccca0SStefano Zampini     ierr = VecNormalize(vecs[i],&norm);CHKERRQ(ierr);
718192cccca0SStefano Zampini     if (norm < PETSC_SMALL) {
718292cccca0SStefano Zampini       ierr = VecSet(vecs[i],0.0);CHKERRQ(ierr);
718392cccca0SStefano Zampini     }
71849a7d3425SStefano Zampini   }
71859a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
71869a7d3425SStefano Zampini   PetscFunctionReturn(0);
71879a7d3425SStefano Zampini }
71889a7d3425SStefano Zampini 
7189bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7190e7931f94SStefano Zampini {
719157de7509SStefano Zampini   Mat            A;
7192e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
7193e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
719452e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
719552e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7196bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
719757de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
719827b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
719927b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
720027b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
720127b6a85dSStefano Zampini   MPI_Comm       subcomm;
720252e5ac9dSStefano Zampini   PetscErrorCode ierr;
7203a57a6d2fSStefano Zampini 
7204e7931f94SStefano Zampini   PetscFunctionBegin;
720557de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
720657de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7207fbfcfee5SBarry 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);
720857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
720957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
72106080607fSStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %D",*n_subdomains);
721157de7509SStefano Zampini 
721257de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
721357de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
721457de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
721557de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
721657de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
7217bb360cb4SStefano Zampini   im_active = !!n;
721857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
721957de7509SStefano Zampini   void_procs = size - active_procs;
722057de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
722157de7509SStefano Zampini   if (void_procs) {
722257de7509SStefano Zampini     PetscInt ncand;
722357de7509SStefano Zampini 
722457de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
722557de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
722657de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
722757de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
722857de7509SStefano Zampini       if (!procs_candidates[i]) {
722957de7509SStefano Zampini         procs_candidates[ncand++] = i;
723057de7509SStefano Zampini       }
723157de7509SStefano Zampini     }
723257de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
723357de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
723457de7509SStefano Zampini   }
723557de7509SStefano Zampini 
7236bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
723714f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
7238bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7239bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
724014f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
724114f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
724214f0bfb9SStefano Zampini     else dest = rank;
724357de7509SStefano Zampini     if (im_active) {
724457de7509SStefano Zampini       issize = 1;
724557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
724614f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
724757de7509SStefano Zampini       } else {
724814f0bfb9SStefano Zampini         isidx = dest;
724957de7509SStefano Zampini       }
725057de7509SStefano Zampini     } else {
725157de7509SStefano Zampini       issize = 0;
725257de7509SStefano Zampini       isidx = -1;
725357de7509SStefano Zampini     }
7254bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
725557de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7256daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
725757de7509SStefano Zampini     PetscFunctionReturn(0);
725857de7509SStefano Zampini   }
7259c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7260c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
726127b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7262e7931f94SStefano Zampini 
7263e7931f94SStefano Zampini   /* Get info on mapping */
72643bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7265e7931f94SStefano Zampini 
7266e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7267785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7268e7931f94SStefano Zampini   xadj[0] = 0;
7269e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7270785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7271785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7272bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
727327b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
727427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
727527b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7276e7931f94SStefano Zampini 
727727b6a85dSStefano Zampini   xadj_count = 0;
72782b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
727927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
728027b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7281d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7282d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7283d023bfaeSStefano Zampini         xadj_count++;
728427b6a85dSStefano Zampini         break;
728527b6a85dSStefano Zampini       }
7286e7931f94SStefano Zampini     }
7287e7931f94SStefano Zampini   }
7288d023bfaeSStefano Zampini   xadj[1] = xadj_count;
728927b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
72903bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7291e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7292e7931f94SStefano Zampini 
72933837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7294e7931f94SStefano Zampini 
729527b6a85dSStefano Zampini   /* Restrict work on active processes only */
729627b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
729727b6a85dSStefano Zampini   if (void_procs) {
729827b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
729927b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
730027b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
730127b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
730227b6a85dSStefano Zampini   } else {
730327b6a85dSStefano Zampini     psubcomm = NULL;
730427b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
730527b6a85dSStefano Zampini   }
730627b6a85dSStefano Zampini 
730727b6a85dSStefano Zampini   v_wgt = NULL;
730827b6a85dSStefano Zampini   if (!color) {
7309e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7310e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7311e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7312c8587f34SStefano Zampini   } else {
731352e5ac9dSStefano Zampini     Mat             subdomain_adj;
731452e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
731552e5ac9dSStefano Zampini     MatPartitioning partitioner;
731627b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
731752e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
731857de7509SStefano Zampini     PetscMPIInt     size;
7319b0c7d250SStefano Zampini     PetscBool       aggregate;
7320b0c7d250SStefano Zampini 
732127b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
732227b6a85dSStefano Zampini     if (void_procs) {
732327b6a85dSStefano Zampini       PetscInt prank = rank;
7324785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
732527b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
7326e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7327e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7328c8587f34SStefano Zampini       }
7329e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
733027b6a85dSStefano Zampini     } else {
733127b6a85dSStefano Zampini       oldranks = NULL;
733227b6a85dSStefano Zampini     }
7333b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
733427b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7335b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7336b0c7d250SStefano Zampini       PetscMPIInt nrank;
7337b0c7d250SStefano Zampini       PetscScalar *vals;
7338b0c7d250SStefano Zampini 
733927b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7340b0c7d250SStefano Zampini       lrows = 0;
7341b0c7d250SStefano Zampini       if (nrank<redprocs) {
7342b0c7d250SStefano Zampini         lrows = size/redprocs;
7343b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7344b0c7d250SStefano Zampini       }
734527b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7346b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7347b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7348b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7349b0c7d250SStefano Zampini       row = nrank;
7350b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7351b0c7d250SStefano Zampini       cols = adjncy;
7352b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7353b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7354b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7355b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7356b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
735752e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
735852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
735952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7360b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
736127b6a85dSStefano Zampini       if (use_vwgt) {
736227b6a85dSStefano Zampini         Vec               v;
736327b6a85dSStefano Zampini         const PetscScalar *array;
736427b6a85dSStefano Zampini         PetscInt          nl;
736527b6a85dSStefano Zampini 
736627b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7367bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
736827b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
736927b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
737027b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
737127b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
737227b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
737322db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
737427b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
737527b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
737627b6a85dSStefano Zampini       }
7377b0c7d250SStefano Zampini     } else {
737827b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
737927b6a85dSStefano Zampini       if (use_vwgt) {
738027b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7381bb360cb4SStefano Zampini         v_wgt[0] = n;
738227b6a85dSStefano Zampini       }
7383b0c7d250SStefano Zampini     }
738422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7385e7931f94SStefano Zampini 
7386e7931f94SStefano Zampini     /* Partition */
738727b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7388ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH)
7389ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH);CHKERRQ(ierr);
7390ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS)
7391ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS);CHKERRQ(ierr);
7392ce64c636SStefano Zampini #else
7393ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE);CHKERRQ(ierr);
7394ce64c636SStefano Zampini #endif
7395e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
739627b6a85dSStefano Zampini     if (v_wgt) {
7397e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7398c8587f34SStefano Zampini     }
739957de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
740057de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7401e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7402e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
740322b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7404e7931f94SStefano Zampini 
740552e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
74066583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
740752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
740852e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
740957de7509SStefano Zampini     if (!aggregate) {
741057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
741127b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
741227b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
741327b6a85dSStefano Zampini #endif
741457de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
741527b6a85dSStefano Zampini       } else if (oldranks) {
7416b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
741727b6a85dSStefano Zampini       } else {
741827b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
741957de7509SStefano Zampini       }
742028143c3dSStefano Zampini     } else {
74217fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7422b0c7d250SStefano Zampini       PetscMPIInt tag;
7423b0c7d250SStefano Zampini       MPI_Request *reqs;
7424b0c7d250SStefano Zampini 
7425b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7426b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7427b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
742827b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
742928143c3dSStefano Zampini       }
74307fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7431b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7432b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
743357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
743427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
743527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
743627b6a85dSStefano Zampini #endif
74377fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
743827b6a85dSStefano Zampini       } else if (oldranks) {
74397fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
744027b6a85dSStefano Zampini       } else {
74417fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7442e7931f94SStefano Zampini       }
744357de7509SStefano Zampini     }
744452e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7445e7931f94SStefano Zampini     /* clean up */
7446e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
744752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7448e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7449e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7450e7931f94SStefano Zampini   }
745127b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
745257de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7453e7931f94SStefano Zampini 
7454e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7455e7931f94SStefano Zampini   i = 1;
745627b6a85dSStefano Zampini   if (!color) i=0;
745757de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7458e7931f94SStefano Zampini   PetscFunctionReturn(0);
7459e7931f94SStefano Zampini }
7460e7931f94SStefano Zampini 
7461e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7462e7931f94SStefano Zampini 
74631e0482f5SStefano 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[])
7464e7931f94SStefano Zampini {
746570cf5478SStefano Zampini   Mat                    local_mat;
7466e7931f94SStefano Zampini   IS                     is_sends_internal;
74679d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
74681ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
74699d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7470e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7471e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7472e7931f94SStefano Zampini   const PetscInt*        is_indices;
7473e7931f94SStefano Zampini   MatType                new_local_type;
7474e7931f94SStefano Zampini   /* buffers */
7475e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
747628143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
74779d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
74781683a169SBarry Smith   PetscScalar            *ptr_vals,*recv_buffer_vals;
74791683a169SBarry Smith   const PetscScalar      *send_buffer_vals;
74801ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7481e7931f94SStefano Zampini   /* MPI */
748228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
748328143c3dSStefano Zampini   PetscSubcomm           subcomm;
7484e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
748528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
748628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
74871ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
74881ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
74891ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7490e7931f94SStefano Zampini   PetscErrorCode         ierr;
7491e7931f94SStefano Zampini 
7492e7931f94SStefano Zampini   PetscFunctionBegin;
749357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7494e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7495fbfcfee5SBarry 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);
749657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
749757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
749857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
749957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
750057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
75011ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
75021ae86dd6SStefano Zampini   if (nvecs) {
75031ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
75041ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
75051ae86dd6SStefano Zampini   }
750657de7509SStefano Zampini   /* further checks */
7507e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7508e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7509e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7510e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7511e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
751257de7509SStefano Zampini   if (reuse && *mat_n) {
751370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
751457de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
751570cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
751628143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
751770cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
751870cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
751970cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
752070cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
752170cf5478SStefano Zampini   }
7522e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7523e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
752457de7509SStefano Zampini 
7525e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7526e7931f94SStefano Zampini   if (!is_sends) {
752728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7528bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7529c8587f34SStefano Zampini   } else {
7530e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7531e7931f94SStefano Zampini     is_sends_internal = is_sends;
7532c8587f34SStefano Zampini   }
7533e7931f94SStefano Zampini 
7534e7931f94SStefano Zampini   /* get comm */
7535a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7536e7931f94SStefano Zampini 
7537e7931f94SStefano Zampini   /* compute number of sends */
7538e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7539e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7540e7931f94SStefano Zampini 
7541e7931f94SStefano Zampini   /* compute number of receives */
7542e569e4e1SStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
7543e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&iflags);CHKERRQ(ierr);
7544*580bdb30SBarry Smith   ierr = PetscArrayzero(iflags,size);CHKERRQ(ierr);
7545e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7546e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7547e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7548e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7549e7931f94SStefano Zampini 
755028143c3dSStefano Zampini   /* restrict comm if requested */
755128143c3dSStefano Zampini   subcomm = 0;
755228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
755328143c3dSStefano Zampini   if (restrict_comm) {
7554779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7555779c1cceSStefano Zampini 
755628143c3dSStefano Zampini     color = 0;
755753a05cb3SStefano Zampini     if (restrict_full) {
755853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
755953a05cb3SStefano Zampini     } else {
756053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
756153a05cb3SStefano Zampini     }
7562b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
7563e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
756428143c3dSStefano Zampini     /* check if reuse has been requested */
756557de7509SStefano Zampini     if (reuse) {
756628143c3dSStefano Zampini       if (*mat_n) {
756728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
756828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
756928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
757028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
757128143c3dSStefano Zampini       } else {
757228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
757328143c3dSStefano Zampini       }
757428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7575779c1cceSStefano Zampini       PetscMPIInt rank;
7576779c1cceSStefano Zampini 
7577779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
757828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
757928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
758028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7581306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
758228143c3dSStefano Zampini     }
758328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
758428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
758528143c3dSStefano Zampini   } else {
758628143c3dSStefano Zampini     comm_n = comm;
758728143c3dSStefano Zampini   }
758828143c3dSStefano Zampini 
7589e7931f94SStefano Zampini   /* prepare send/receive buffers */
7590e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_idxs);CHKERRQ(ierr);
7591*580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_idxs,size);CHKERRQ(ierr);
7592e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_vals);CHKERRQ(ierr);
7593*580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_vals,size);CHKERRQ(ierr);
759428143c3dSStefano Zampini   if (nis) {
7595e569e4e1SStefano Zampini     ierr = PetscCalloc1(size,&ilengths_idxs_is);CHKERRQ(ierr);
759628143c3dSStefano Zampini   }
7597e7931f94SStefano Zampini 
759828143c3dSStefano Zampini   /* Get data from local matrices */
75996c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7600e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7601e7931f94SStefano Zampini     /*
7602e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7603e7931f94SStefano Zampini        send_buffer_idxs should contain:
7604e7931f94SStefano Zampini        - MatType_PRIVATE type
7605e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7606e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7607e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7608e7931f94SStefano Zampini     */
76096c4ed002SBarry Smith   else {
76101683a169SBarry Smith     ierr = MatDenseGetArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
76113bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7612854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7613e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7614e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
76153bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7616*580bdb30SBarry Smith     ierr = PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i);CHKERRQ(ierr);
76173bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7618e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7619e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7620e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7621e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7622c8587f34SStefano Zampini     }
7623c8587f34SStefano Zampini   }
7624e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
762528143c3dSStefano Zampini   /* additional is (if any) */
762628143c3dSStefano Zampini   if (nis) {
762728143c3dSStefano Zampini     PetscMPIInt psum;
762828143c3dSStefano Zampini     PetscInt j;
762928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
763028143c3dSStefano Zampini       PetscInt plen;
763128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
763228143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
763328143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
763428143c3dSStefano Zampini     }
7635854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
763628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
763728143c3dSStefano Zampini       PetscInt plen;
763828143c3dSStefano Zampini       const PetscInt *is_array_idxs;
763928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
764028143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
764128143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
7642*580bdb30SBarry Smith       ierr = PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen);CHKERRQ(ierr);
764328143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
764428143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
764528143c3dSStefano Zampini     }
764628143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
764728143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
764828143c3dSStefano Zampini     }
764928143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
765028143c3dSStefano Zampini   }
76513b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
765228143c3dSStefano Zampini 
7653e7931f94SStefano Zampini   buf_size_idxs = 0;
7654e7931f94SStefano Zampini   buf_size_vals = 0;
765528143c3dSStefano Zampini   buf_size_idxs_is = 0;
76561ae86dd6SStefano Zampini   buf_size_vecs = 0;
7657e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7658e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7659e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
766028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
76611ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7662e7931f94SStefano Zampini   }
7663785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7664785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
766595ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
76661ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7667e7931f94SStefano Zampini 
7668e7931f94SStefano Zampini   /* get new tags for clean communications */
7669e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7670e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
767128143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
76721ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7673e7931f94SStefano Zampini 
7674e7931f94SStefano Zampini   /* allocate for requests */
7675785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7676785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
767795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
76781ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7679785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7680785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
768195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
76821ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7683e7931f94SStefano Zampini 
7684e7931f94SStefano Zampini   /* communications */
7685e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7686e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
768728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
76881ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7689e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7690e7931f94SStefano Zampini     source_dest = onodes[i];
7691e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7692e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7693e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7694e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
769528143c3dSStefano Zampini     if (nis) {
769657de7509SStefano Zampini       source_dest = onodes_is[i];
769728143c3dSStefano 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);
769828143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
769928143c3dSStefano Zampini     }
77001ae86dd6SStefano Zampini     if (nvecs) {
77011ae86dd6SStefano Zampini       source_dest = onodes[i];
77021ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
77031ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
77041ae86dd6SStefano Zampini     }
7705e7931f94SStefano Zampini   }
7706e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7707e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7708e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7709e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
771028143c3dSStefano Zampini     if (nis) {
771128143c3dSStefano 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);
771228143c3dSStefano Zampini     }
77131ae86dd6SStefano Zampini     if (nvecs) {
77141ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77151ae86dd6SStefano 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);
77161ae86dd6SStefano Zampini     }
7717e7931f94SStefano Zampini   }
7718e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7719e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7720e7931f94SStefano Zampini 
7721e7931f94SStefano Zampini   /* assemble new l2g map */
7722e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7723e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
77249d30be91SStefano Zampini   new_local_rows = 0;
7725e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
77269d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7727e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7728e7931f94SStefano Zampini   }
77299d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7730e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
77319d30be91SStefano Zampini   new_local_rows = 0;
7732e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7733*580bdb30SBarry Smith     ierr = PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1));CHKERRQ(ierr);
77349d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7735e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7736e7931f94SStefano Zampini   }
77379d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
77389d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7739e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7740e7931f94SStefano Zampini 
7741e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7742e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7743e7931f94SStefano 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) */
7744e7931f94SStefano Zampini   if (n_recvs) {
774528143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7746e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7747e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7748e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7749e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7750e7931f94SStefano Zampini         break;
7751e7931f94SStefano Zampini       }
7752e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7753e7931f94SStefano Zampini     }
7754e7931f94SStefano Zampini     switch (new_local_type_private) {
775528143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7756e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7757e7931f94SStefano Zampini         bs = 1;
7758e7931f94SStefano Zampini         break;
7759e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7760e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7761e7931f94SStefano Zampini         bs = 1;
7762e7931f94SStefano Zampini         break;
7763e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7764e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7765e7931f94SStefano Zampini         break;
7766e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7767e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7768e7931f94SStefano Zampini         break;
7769e7931f94SStefano Zampini       default:
7770fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7771e7931f94SStefano Zampini         break;
7772e7931f94SStefano Zampini     }
7773ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7774ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
777528143c3dSStefano Zampini     bs = 1;
7776e7931f94SStefano Zampini   }
7777e7931f94SStefano Zampini 
777870cf5478SStefano Zampini   /* create MATIS object if needed */
777957de7509SStefano Zampini   if (!reuse) {
7780e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7781e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
778270cf5478SStefano Zampini   } else {
778370cf5478SStefano Zampini     /* it also destroys the local matrices */
778457de7509SStefano Zampini     if (*mat_n) {
778570cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
778657de7509SStefano Zampini     } else { /* this is a fake object */
778757de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
778857de7509SStefano Zampini     }
778970cf5478SStefano Zampini   }
779070cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7791e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
77929d30be91SStefano Zampini 
77939d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77949d30be91SStefano Zampini 
77959d30be91SStefano Zampini   /* Global to local map of received indices */
77969d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
77979d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
77989d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
77999d30be91SStefano Zampini 
78009d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
78019d30be91SStefano Zampini   buf_size_idxs = 0;
78029d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
78039d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
78049d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
78059d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
78069d30be91SStefano Zampini   }
78079d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
78089d30be91SStefano Zampini 
78099d30be91SStefano Zampini   /* set preallocation */
78109d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
78119d30be91SStefano Zampini   if (!newisdense) {
78129d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
78139d30be91SStefano Zampini 
78149d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
78159d30be91SStefano Zampini     if (n_recvs) {
78169d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
78179d30be91SStefano Zampini     }
78189d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
78199d30be91SStefano Zampini       PetscInt j;
78209d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
78219d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
78229d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
78239d30be91SStefano Zampini         }
78249d30be91SStefano Zampini       } else {
78259d30be91SStefano Zampini         /* TODO */
78269d30be91SStefano Zampini       }
78279d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
78289d30be91SStefano Zampini     }
78299d30be91SStefano Zampini     if (new_local_nnz) {
78309d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
78319d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
78329d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
78339d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
78349d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
78359d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
78369d30be91SStefano Zampini     } else {
78379d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
78389d30be91SStefano Zampini     }
78399d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
78409d30be91SStefano Zampini   } else {
78419d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
78429d30be91SStefano Zampini   }
7843e7931f94SStefano Zampini 
7844e7931f94SStefano Zampini   /* set values */
7845e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
78469d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7847e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7848e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7849e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
78509d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7851e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7852e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7853e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
785428143c3dSStefano Zampini     } else {
785528143c3dSStefano Zampini       /* TODO */
7856e7931f94SStefano Zampini     }
7857e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7858e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7859e7931f94SStefano Zampini   }
7860e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7861e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78623b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
786370cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
786470cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78659d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7866e7931f94SStefano Zampini 
7867dfd14d43SStefano Zampini #if 0
786828143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7869e7931f94SStefano Zampini     Vec       lvec,rvec;
7870e7931f94SStefano Zampini     PetscReal infty_error;
7871e7931f94SStefano Zampini 
78722a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7873e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7874e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7875e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
787670cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7877e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7878e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7879e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7880e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7881e7931f94SStefano Zampini   }
788228143c3dSStefano Zampini #endif
7883e7931f94SStefano Zampini 
788428143c3dSStefano Zampini   /* assemble new additional is (if any) */
788528143c3dSStefano Zampini   if (nis) {
788628143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
788728143c3dSStefano Zampini 
788828143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7889854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
789028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
789128143c3dSStefano Zampini     psum = 0;
789228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
789328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
789428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
789528143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
789628143c3dSStefano Zampini         psum += plen;
789728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
789828143c3dSStefano Zampini       }
789928143c3dSStefano Zampini     }
7900854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7901854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
790228143c3dSStefano Zampini     for (i=1;i<nis;i++) {
790328143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
790428143c3dSStefano Zampini     }
7905*580bdb30SBarry Smith     ierr = PetscArrayzero(count_is,nis);CHKERRQ(ierr);
790628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
790728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
790828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
790928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
7910*580bdb30SBarry Smith         ierr = PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen);CHKERRQ(ierr);
791128143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
791228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
791328143c3dSStefano Zampini       }
791428143c3dSStefano Zampini     }
791528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
791628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
791728143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
791828143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
791928143c3dSStefano Zampini     }
792028143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
792128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
792228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
792328143c3dSStefano Zampini   }
7924e7931f94SStefano Zampini   /* free workspace */
792528143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7926e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7927e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7928e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7929e7931f94SStefano Zampini   if (isdense) {
7930e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
79311683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
79323b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7933e7931f94SStefano Zampini   } else {
7934e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7935e7931f94SStefano Zampini   }
793628143c3dSStefano Zampini   if (nis) {
793728143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
793828143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
793928143c3dSStefano Zampini   }
79401ae86dd6SStefano Zampini 
79411ae86dd6SStefano Zampini   if (nvecs) {
79421ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
79431ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
79441ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
79451ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
79461ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
79471ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
79481ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
79491ae86dd6SStefano Zampini     /* set values */
79501ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
79511ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
79521ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
79531ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
79541ae86dd6SStefano Zampini       PetscInt j;
79551ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
79561ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
79571ae86dd6SStefano Zampini       }
79581ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
79591ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
79601ae86dd6SStefano Zampini     }
79611ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
79621ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
79631ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
79641ae86dd6SStefano Zampini   }
79651ae86dd6SStefano Zampini 
79661ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
79671ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7968e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7969e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
79701ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
797128143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7972e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7973e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
79741ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
797528143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7976e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7977e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7978e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7979e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7980e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
798128143c3dSStefano Zampini   if (nis) {
798228143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
798328143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
798428143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
798528143c3dSStefano Zampini   }
798628143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
798728143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
798828143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
798928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
799028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
799128143c3dSStefano Zampini     }
79921ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
79931ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
79941ae86dd6SStefano Zampini     }
799553a05cb3SStefano Zampini     *mat_n = NULL;
799628143c3dSStefano Zampini   }
7997e7931f94SStefano Zampini   PetscFunctionReturn(0);
7998e7931f94SStefano Zampini }
7999a57a6d2fSStefano Zampini 
800012edc857SStefano Zampini /* temporary hack into ksp private data structure */
8001af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
800212edc857SStefano Zampini 
8003c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
8004c8587f34SStefano Zampini {
8005c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
8006c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
800720a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
80081ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
80091e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
80109881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
801120a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
80124f819b78SStefano Zampini   IS                     coarse_is,*isarray,corners;
80136e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
801430368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
8015e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
8016f9eb5b7dSStefano Zampini   PC                     pc_temp;
8017c8587f34SStefano Zampini   PCType                 coarse_pc_type;
8018c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
8019f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
80207274672aSStefano Zampini   PetscBool              coarse_reuse;
80211e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
802268457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
802322bc73bbSStefano Zampini   PetscScalar            *array;
802457de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
802557de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
8026e569e4e1SStefano Zampini   PetscMPIInt            size;
80279881197aSStefano Zampini   PetscErrorCode         ierr;
8028fdc09c96SStefano Zampini 
8029c8587f34SStefano Zampini   PetscFunctionBegin;
803043371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8031c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
803268457ee5SStefano 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 */
8033fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
80345a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
80357de4f681Sstefano_zampini 
80367de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
8037fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
8038f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
8039f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
8040f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
8041fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
804251bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
804351bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
8044727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
8045fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
8046fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
8047fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
8048f4ddd8eeSStefano Zampini       }
8049fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
8050fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
8051f4ddd8eeSStefano Zampini     }
805270cf5478SStefano Zampini     /* reset any subassembling information */
805357de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
805470cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
805557de7509SStefano Zampini     }
80566e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
8057fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
8058f4ddd8eeSStefano Zampini   }
805957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
806057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
806157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
806257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
806318a45a71SStefano Zampini   } else {
806457de7509SStefano Zampini     coarse_mat = NULL;
806557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
80666e683305SStefano Zampini   }
8067e7931f94SStefano Zampini 
8068abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
8069abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
8070abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
8071abbbba34SStefano Zampini 
8072abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
80734f819b78SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense);CHKERRQ(ierr);
8074e176bc59SStefano 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);
80756e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
80766e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
80776e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8078abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
8079abbbba34SStefano Zampini 
808057de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
808157de7509SStefano Zampini   im_active = !!(pcis->n);
808257de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
808357de7509SStefano Zampini 
808414f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
808557de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
808657de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
8087e569e4e1SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
808857de7509SStefano Zampini   coarse_mat_is        = NULL;
808957de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
809057de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
8091e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
8092ce64c636SStefano Zampini   if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size;
809357de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
8094e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
809557de7509SStefano Zampini   if (multilevel_requested) {
809657de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
809757de7509SStefano Zampini     restr      = PETSC_FALSE;
809857de7509SStefano Zampini     full_restr = PETSC_FALSE;
809957de7509SStefano Zampini   } else {
8100e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
810157de7509SStefano Zampini     restr      = PETSC_TRUE;
810257de7509SStefano Zampini     full_restr = PETSC_TRUE;
810357de7509SStefano Zampini   }
8104e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
810557de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
810657de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
8107a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
8108bb360cb4SStefano Zampini       if (multilevel_requested) {
8109bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8110bb360cb4SStefano Zampini       } else {
8111bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8112bb360cb4SStefano Zampini       }
8113a198735bSStefano Zampini     } else {
81147de4f681Sstefano_zampini       PetscMPIInt rank;
8115a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
8116e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
8117a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
8118a198735bSStefano Zampini     }
811957de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
812057de7509SStefano Zampini     PetscInt    psum;
812157de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
812257de7509SStefano Zampini     else psum = 0;
812357de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8124075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
812557de7509SStefano Zampini   }
812657de7509SStefano Zampini   /* determine if we can go multilevel */
812757de7509SStefano Zampini   if (multilevel_requested) {
812857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
812957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
813057de7509SStefano Zampini   }
813157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
813257de7509SStefano Zampini 
8133e4d548c7SStefano Zampini   /* dump subassembling pattern */
8134e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
8135e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
8136e4d548c7SStefano Zampini   }
81376e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
81381e0482f5SStefano Zampini   nedcfield = -1;
81394f819b78SStefano Zampini   corners = NULL;
81404f819b78SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneded computations */
81416e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
81426e683305SStefano Zampini     const PetscInt         *idxs;
81436e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
81446e683305SStefano Zampini 
81456e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
81460be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
81476e683305SStefano Zampini     /* allocate space for temporary storage */
8148854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
8149854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
81506e683305SStefano Zampini     /* allocate for IS array */
81516e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
81521e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
81531e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
81541e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
81551e0482f5SStefano Zampini       } else {
81561e0482f5SStefano Zampini         nedcfield = 0;
81576080607fSStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%D)",nisdofs);
81581e0482f5SStefano Zampini         nisdofs = 1;
81591e0482f5SStefano Zampini       }
81601e0482f5SStefano Zampini     }
81616e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
816227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
816330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
8164854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
81656e683305SStefano Zampini     /* dofs splitting */
81666e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
81676e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
81681e0482f5SStefano Zampini       if (nedcfield != i) {
81696e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
81706e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
81716e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
81726e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
81731e0482f5SStefano Zampini       } else {
81741e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
81751e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
81761e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
81776080607fSStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %D != %D",tsize,nout);
81781e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
81791e0482f5SStefano Zampini       }
81806e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
818130368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
81826e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
81836e683305SStefano Zampini     }
81846e683305SStefano Zampini     /* neumann boundaries */
81856e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
81866e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
81876e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
81886e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
81896e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
81906e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
81916e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
819230368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
81936e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
81946e683305SStefano Zampini     }
81954f819b78SStefano Zampini     /* coordinates */
81964f819b78SStefano Zampini     if (pcbddc->corner_selected) {
81974f819b78SStefano Zampini       ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
81984f819b78SStefano Zampini       ierr = ISGetLocalSize(corners,&tsize);CHKERRQ(ierr);
81994f819b78SStefano Zampini       ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
82004f819b78SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
82014f819b78SStefano Zampini       if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %D != %D",tsize,nout);
82024f819b78SStefano Zampini       ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
82034f819b78SStefano Zampini       ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
82044f819b78SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
82054f819b78SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners);CHKERRQ(ierr);
82064f819b78SStefano Zampini     }
82076e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
82086e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
82096e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
82106e683305SStefano Zampini   } else {
82116e683305SStefano Zampini     nis = 0;
82126e683305SStefano Zampini     nisdofs = 0;
82136e683305SStefano Zampini     nisneu = 0;
821430368db7SStefano Zampini     nisvert = 0;
82156e683305SStefano Zampini     isarray = NULL;
82166e683305SStefano Zampini   }
82176e683305SStefano Zampini   /* destroy no longer needed map */
82186e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
82196e683305SStefano Zampini 
822057de7509SStefano Zampini   /* subassemble */
822157de7509SStefano Zampini   if (multilevel_allowed) {
82221ae86dd6SStefano Zampini     Vec       vp[1];
82231ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
822457de7509SStefano Zampini     PetscBool reuse,reuser;
82251ae86dd6SStefano Zampini 
822657de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
822757de7509SStefano Zampini     else reuse = PETSC_FALSE;
822857de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
82291ae86dd6SStefano Zampini     vp[0] = NULL;
82301ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
82311ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
82321ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
82331ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
82341ae86dd6SStefano Zampini       nvecs = 1;
82351ae86dd6SStefano Zampini 
82361ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8237a198735bSStefano Zampini         Mat      B,loc_divudotp;
82381ae86dd6SStefano Zampini         Vec      v,p;
82391ae86dd6SStefano Zampini         IS       dummy;
82401ae86dd6SStefano Zampini         PetscInt np;
82411ae86dd6SStefano Zampini 
8242a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8243a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
82441ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
82457dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
82461ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
82471ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
82481ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
82491ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
82501ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
82511ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
82521ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
82531ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
82541ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
82551ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
82561ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
82571ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
825874e2c79eSStefano Zampini       }
82591ae86dd6SStefano Zampini     }
82601ae86dd6SStefano Zampini     if (reuser) {
82611e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
826274e2c79eSStefano Zampini     } else {
82631e0482f5SStefano 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);
82641ae86dd6SStefano Zampini     }
82651ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
82661683a169SBarry Smith       PetscScalar       *arraym;
82671683a169SBarry Smith       const PetscScalar *arrayv;
82681ae86dd6SStefano Zampini       PetscInt          nl;
82691ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
82701ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
82711ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
82721683a169SBarry Smith       ierr = VecGetArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
8273*580bdb30SBarry Smith       ierr = PetscArraycpy(arraym,arrayv,nl);CHKERRQ(ierr);
82741683a169SBarry Smith       ierr = VecRestoreArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
82751ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
82761ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8277a198735bSStefano Zampini     } else {
8278a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
82791ae86dd6SStefano Zampini     }
82801ae86dd6SStefano Zampini   } else {
82811e0482f5SStefano 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);
82826e683305SStefano Zampini   }
828357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
828457de7509SStefano Zampini     if (!multilevel_allowed) {
8285487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
82866e683305SStefano Zampini     } else {
828757de7509SStefano Zampini       Mat A;
8288779c1cceSStefano Zampini 
828957de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
829057de7509SStefano Zampini       if (coarse_mat_is) {
829157de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
829257de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
829357de7509SStefano Zampini         coarse_mat = coarse_mat_is;
829457de7509SStefano Zampini       }
829557de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
829657de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
829757de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
8298779c1cceSStefano Zampini     }
8299779c1cceSStefano Zampini   }
830057de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
830157de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
83026e683305SStefano Zampini 
83036e683305SStefano Zampini   /* create local to global scatters for coarse problem */
830468457ee5SStefano Zampini   if (compute_vecs) {
83056e683305SStefano Zampini     PetscInt lrows;
83066e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
830757de7509SStefano Zampini     if (coarse_mat) {
830857de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
83096e683305SStefano Zampini     } else {
83106e683305SStefano Zampini       lrows = 0;
83116e683305SStefano Zampini     }
83126e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
83136e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
831489535278SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD);CHKERRQ(ierr);
83156e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
83169448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
83176e683305SStefano Zampini   }
83186e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8319c8587f34SStefano Zampini 
8320f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8321f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8322f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8323f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8324f9eb5b7dSStefano Zampini   } else {
8325f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8326f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8327c8587f34SStefano Zampini   }
8328c8587f34SStefano Zampini 
83296e683305SStefano Zampini   /* print some info if requested */
83306e683305SStefano Zampini   if (pcbddc->dbg_flag) {
83316e683305SStefano Zampini     if (!multilevel_allowed) {
83326e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
83336e683305SStefano Zampini       if (multilevel_requested) {
83346080607fSStefano 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);
83356e683305SStefano Zampini       } else if (pcbddc->max_levels) {
83366080607fSStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%D)\n",pcbddc->max_levels);CHKERRQ(ierr);
83376e683305SStefano Zampini       }
83386e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
83396e683305SStefano Zampini     }
83406e683305SStefano Zampini   }
83416e683305SStefano Zampini 
83421e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
83431e0482f5SStefano Zampini   coarseG = NULL;
83441e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
83451e0482f5SStefano Zampini     MPI_Comm ccomm;
83461e0482f5SStefano Zampini     if (coarse_mat) {
83471e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
83481e0482f5SStefano Zampini     } else {
83491e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
83501e0482f5SStefano Zampini     }
83511e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
83521e0482f5SStefano Zampini   }
83531e0482f5SStefano Zampini 
8354f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
835557de7509SStefano Zampini   if (coarse_mat) {
83567274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
83576a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
83587274672aSStefano Zampini 
83596e683305SStefano Zampini     if (pcbddc->dbg_flag) {
836057de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
83616e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
83626e683305SStefano Zampini     }
8363f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8364312be037SStefano Zampini       char   prefix[256],str_level[16];
8365e604994aSStefano Zampini       size_t len;
83661e0482f5SStefano Zampini 
836757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8368422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8369c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8370f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
837157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8372c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
83736e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8374c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
83751e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8376c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8377e604994aSStefano Zampini       /* prefix */
8378e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8379e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8380e604994aSStefano Zampini       if (!pcbddc->current_level) {
8381a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8382a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8383c8587f34SStefano Zampini       } else {
8384e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8385312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8386312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8387a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
838834d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
838935529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8390a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8391e604994aSStefano Zampini       }
8392e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
83933e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
83943e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
83953e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
83963e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8397f9eb5b7dSStefano Zampini       /* allow user customization */
8398f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
8399e569e4e1SStefano Zampini       /* get some info after set from options */
8400e569e4e1SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
8401e569e4e1SStefano Zampini       /* multilevel cannot be done with coarse PCs different from BDDC or NN */
8402e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8403e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
8404e569e4e1SStefano Zampini       if (multilevel_allowed && !isbddc && !isnn) {
8405e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
8406e569e4e1SStefano Zampini         ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8407e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
8408e569e4e1SStefano Zampini         ierr   = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
8409e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
84104f819b78SStefano Zampini         if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */
84114f819b78SStefano Zampini           ierr = PetscObjectOptionsBegin((PetscObject)pc_temp);CHKERRQ(ierr);
84124f819b78SStefano Zampini           ierr = (*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp);CHKERRQ(ierr);
84134f819b78SStefano Zampini           ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp);CHKERRQ(ierr);
84144f819b78SStefano Zampini           ierr = PetscOptionsEnd();CHKERRQ(ierr);
84154f819b78SStefano Zampini           pc_temp->setfromoptionscalled++;
84164f819b78SStefano Zampini         }
8417e569e4e1SStefano Zampini       }
84183e3c6dadSStefano Zampini     }
84193e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
842051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
84213e3c6dadSStefano Zampini     if (nisdofs) {
84223e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
84233e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
84243e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
84253e3c6dadSStefano Zampini       }
84263e3c6dadSStefano Zampini     }
84273e3c6dadSStefano Zampini     if (nisneu) {
84283e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
84293e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8430312be037SStefano Zampini     }
843130368db7SStefano Zampini     if (nisvert) {
843230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
843330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
843430368db7SStefano Zampini     }
84351e0482f5SStefano Zampini     if (coarseG) {
84361e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
84371e0482f5SStefano Zampini     }
8438f9eb5b7dSStefano Zampini 
8439f9eb5b7dSStefano Zampini     /* get some info after set from options */
8440f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
84414f819b78SStefano Zampini 
8442b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8443b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8444f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8445f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
8446f9eb5b7dSStefano Zampini     }
8447b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
84487274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
84497274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
8450b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8451b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
8452b76f3995Sstefano_zampini     }
84537274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
84544f3a063dSStefano Zampini     if (isredundant) {
84554f3a063dSStefano Zampini       KSP inner_ksp;
84564f3a063dSStefano Zampini       PC  inner_pc;
84579326c5c6Sstefano_zampini 
84584f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
84594f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
84604f3a063dSStefano Zampini     }
8461f9eb5b7dSStefano Zampini 
846257de7509SStefano Zampini     /* parameters which miss an API */
84637274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
846457de7509SStefano Zampini     if (isbddc) {
8465720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
84667274672aSStefano Zampini 
8467720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
846857de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8469e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
847027b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
847127b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8472a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8473a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8474a198735bSStefano Zampini         IS                     row,col;
8475a198735bSStefano Zampini         const PetscInt         *gidxs;
8476a198735bSStefano Zampini         PetscInt               n,st,M,N;
8477a198735bSStefano Zampini 
8478a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8479a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8480a198735bSStefano Zampini         st   = st-n;
8481a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8482a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8483a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8484a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8485a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8486a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8487a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8488a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8489a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8490a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8491a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8492a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8493a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8494a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8495a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8496a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8497a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8498a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8499a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8500a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
85018ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8502a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8503720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8504bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8505720d30f9SStefano Zampini       }
8506d4d8cf7bSStefano Zampini     }
85079881197aSStefano Zampini 
85083301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
85095a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
85103301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
85113301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
85123301b35fSStefano Zampini     }
85133301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
85143301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
85153301b35fSStefano Zampini     }
85163301b35fSStefano Zampini     if (pc->pmat->spd_set) {
85173301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
85183301b35fSStefano Zampini     }
851927b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
852027b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
852127b6a85dSStefano Zampini     }
85226e683305SStefano Zampini     /* set operators */
852304fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
85243007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix);CHKERRQ(ierr);
85255f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
85266e683305SStefano Zampini     if (pcbddc->dbg_flag) {
85276e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
85286e683305SStefano Zampini     }
85296e683305SStefano Zampini   }
85301e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
85316e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8532b1ecc7b1SStefano Zampini #if 0
8533b9b85e73SStefano Zampini   {
8534b9b85e73SStefano Zampini     PetscViewer viewer;
8535b9b85e73SStefano Zampini     char filename[256];
8536b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8537b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
85386a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8539b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8540f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8541b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8542b9b85e73SStefano Zampini   }
8543b9b85e73SStefano Zampini #endif
8544f9eb5b7dSStefano Zampini 
85454f819b78SStefano Zampini   if (corners) {
85464f819b78SStefano Zampini     Vec            gv;
85474f819b78SStefano Zampini     IS             is;
85484f819b78SStefano Zampini     const PetscInt *idxs;
85494f819b78SStefano Zampini     PetscInt       i,d,N,n,cdim = pcbddc->mat_graph->cdim;
85504f819b78SStefano Zampini     PetscScalar    *coords;
85514f819b78SStefano Zampini 
85524f819b78SStefano Zampini     if (!pcbddc->mat_graph->cloc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates");
85534f819b78SStefano Zampini     ierr = VecGetSize(pcbddc->coarse_vec,&N);CHKERRQ(ierr);
85544f819b78SStefano Zampini     ierr = VecGetLocalSize(pcbddc->coarse_vec,&n);CHKERRQ(ierr);
85554f819b78SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv);CHKERRQ(ierr);
85564f819b78SStefano Zampini     ierr = VecSetBlockSize(gv,cdim);CHKERRQ(ierr);
85574f819b78SStefano Zampini     ierr = VecSetSizes(gv,n*cdim,N*cdim);CHKERRQ(ierr);
85584f819b78SStefano Zampini     ierr = VecSetType(gv,VECSTANDARD);CHKERRQ(ierr);
85594f819b78SStefano Zampini     ierr = VecSetFromOptions(gv);CHKERRQ(ierr);
85604f819b78SStefano Zampini     ierr = VecSet(gv,PETSC_MAX_REAL);CHKERRQ(ierr); /* we only propagate coordinates from vertices constraints */
85614f819b78SStefano Zampini 
85624f819b78SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
85634f819b78SStefano Zampini     ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
85644f819b78SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
85654f819b78SStefano Zampini     ierr = PetscMalloc1(n*cdim,&coords);CHKERRQ(ierr);
85664f819b78SStefano Zampini     for (i=0;i<n;i++) {
85674f819b78SStefano Zampini       for (d=0;d<cdim;d++) {
85684f819b78SStefano Zampini         coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d];
85694f819b78SStefano Zampini       }
85704f819b78SStefano Zampini     }
85714f819b78SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
85724f819b78SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
85734f819b78SStefano Zampini 
85744f819b78SStefano Zampini     ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
85754f819b78SStefano Zampini     ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
85764f819b78SStefano Zampini     ierr = VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES);CHKERRQ(ierr);
85774f819b78SStefano Zampini     ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
85784f819b78SStefano Zampini     ierr = PetscFree(coords);CHKERRQ(ierr);
85794f819b78SStefano Zampini     ierr = VecAssemblyBegin(gv);CHKERRQ(ierr);
85804f819b78SStefano Zampini     ierr = VecAssemblyEnd(gv);CHKERRQ(ierr);
85814f819b78SStefano Zampini     ierr = VecGetArray(gv,&coords);CHKERRQ(ierr);
85824f819b78SStefano Zampini     if (pcbddc->coarse_ksp) {
85834f819b78SStefano Zampini       PC        coarse_pc;
85844f819b78SStefano Zampini       PetscBool isbddc;
85854f819b78SStefano Zampini 
85864f819b78SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
85874f819b78SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
85884f819b78SStefano Zampini       if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */
85894f819b78SStefano Zampini         PetscReal *realcoords;
85904f819b78SStefano Zampini 
85914f819b78SStefano Zampini         ierr = VecGetLocalSize(gv,&n);CHKERRQ(ierr);
85924f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
85934f819b78SStefano Zampini         ierr = PetscMalloc1(n,&realcoords);CHKERRQ(ierr);
85944f819b78SStefano Zampini         for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]);
85954f819b78SStefano Zampini #else
85964f819b78SStefano Zampini         realcoords = coords;
85974f819b78SStefano Zampini #endif
85984f819b78SStefano Zampini         ierr = PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords);CHKERRQ(ierr);
85994f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86004f819b78SStefano Zampini         ierr = PetscFree(realcoords);CHKERRQ(ierr);
86014f819b78SStefano Zampini #endif
86024f819b78SStefano Zampini       }
86034f819b78SStefano Zampini     }
86044f819b78SStefano Zampini     ierr = VecRestoreArray(gv,&coords);CHKERRQ(ierr);
86054f819b78SStefano Zampini     ierr = VecDestroy(&gv);CHKERRQ(ierr);
86064f819b78SStefano Zampini   }
86074f819b78SStefano Zampini   ierr = ISDestroy(&corners);CHKERRQ(ierr);
86084f819b78SStefano Zampini 
860998a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
861098a51de6SStefano Zampini     Vec crhs,csol;
861104708bb6SStefano Zampini 
8612f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8613f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8614f347579bSStefano Zampini     if (!csol) {
86152a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8616f9eb5b7dSStefano Zampini     }
8617f347579bSStefano Zampini     if (!crhs) {
86182a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8619f347579bSStefano Zampini     }
8620b0f5fe93SStefano Zampini   }
86211ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8622b0f5fe93SStefano Zampini 
8623b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8624b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8625b0f5fe93SStefano Zampini 
8626b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
86274f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
86284f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
86294f1b2e48SStefano Zampini     }
8630b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8631b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8632b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8633b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8634b0f5fe93SStefano Zampini     if (coarse_mat) {
8635b0f5fe93SStefano Zampini       Vec         nullv;
8636b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8637b0f5fe93SStefano Zampini       PetscInt    nl;
8638b0f5fe93SStefano Zampini 
8639b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8640b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8641b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8642b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8643*580bdb30SBarry Smith       ierr = PetscArraycpy(array2,array,nl);CHKERRQ(ierr);
8644b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8645b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8646b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8647b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8648b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8649b0f5fe93SStefano Zampini     }
8650b0f5fe93SStefano Zampini   }
865143371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8652b0f5fe93SStefano Zampini 
865343371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8654b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8655b0f5fe93SStefano Zampini     PetscBool ispreonly;
8656b0f5fe93SStefano Zampini 
8657b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8658b0f5fe93SStefano Zampini       PetscBool isnull;
8659b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8660bef83e63SStefano Zampini       if (isnull) {
8661b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8662b0f5fe93SStefano Zampini       }
8663bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8664b0f5fe93SStefano Zampini     }
8665b0f5fe93SStefano Zampini     /* setup coarse ksp */
8666b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8667cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8668cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
86696e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8670c8587f34SStefano Zampini       KSP       check_ksp;
86712b510759SStefano Zampini       KSPType   check_ksp_type;
8672c8587f34SStefano Zampini       PC        check_pc;
86736e683305SStefano Zampini       Vec       check_vec,coarse_vec;
86746a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
86752b510759SStefano Zampini       PetscInt  its;
86766e683305SStefano Zampini       PetscBool compute_eigs;
86776e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
86786e683305SStefano Zampini       PetscInt  neigs;
86798e185a42SStefano Zampini       const char *prefix;
8680c8587f34SStefano Zampini 
86812b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
86826e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
868315579a77SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0);CHKERRQ(ierr);
8684399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
868523ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8686f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8687e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8688e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8689e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
86902b510759SStefano Zampini       if (ispreonly) {
86912b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
86926e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
86932b510759SStefano Zampini       } else {
8694cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
86956e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8696c8587f34SStefano Zampini       }
8697c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
86986e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
86996e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
87006e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8701a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8702a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8703a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8704a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8705c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8706c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8707c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8708c8587f34SStefano Zampini       /* create random vec */
87092701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8710c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
87116e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8712c8587f34SStefano Zampini       /* solve coarse problem */
87136e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8714c0decd05SBarry Smith       ierr = KSPCheckSolve(check_ksp,pc,coarse_vec);CHKERRQ(ierr);
8715cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
87166e683305SStefano Zampini       if (compute_eigs) {
8717854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8718854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
87196e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
87201ae86dd6SStefano Zampini         if (neigs) {
87216e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
87226e683305SStefano Zampini           lambda_min = eigs_r[0];
87236e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
87242701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
87252701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8726cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8727cbcc2c2aSStefano Zampini             }
8728c8587f34SStefano Zampini           }
8729c8587f34SStefano Zampini         }
87301ae86dd6SStefano Zampini       }
8731cbcc2c2aSStefano Zampini 
8732c8587f34SStefano Zampini       /* check coarse problem residual error */
87336e683305SStefano Zampini       if (pcbddc->dbg_flag) {
87346e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
87356e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
87366e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8737c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
87386e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
87396e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8740779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
87416e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
87426e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
87436e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
87446e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8745b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8746b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8747b0f5fe93SStefano Zampini         }
87486e683305SStefano Zampini         if (compute_eigs) {
87496e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8750b03ebc13SStefano Zampini           KSPConvergedReason reason;
8751deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8752c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8753b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
87546e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8755b03ebc13SStefano 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);
87566e683305SStefano Zampini           for (i=0;i<neigs;i++) {
87576e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8758c8587f34SStefano Zampini           }
87596e683305SStefano Zampini         }
87606e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
87616e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
87626e683305SStefano Zampini       }
8763e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
87642701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8765c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
87666e683305SStefano Zampini       if (compute_eigs) {
87676e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
87686e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8769c8587f34SStefano Zampini       }
87706e683305SStefano Zampini     }
87716e683305SStefano Zampini   }
8772bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8773cbcc2c2aSStefano Zampini   /* print additional info */
8774cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
87756e683305SStefano Zampini     /* waits until all processes reaches this point */
87766e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
87776080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %D\n",pcbddc->current_level);CHKERRQ(ierr);
8778cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8779cbcc2c2aSStefano Zampini   }
8780cbcc2c2aSStefano Zampini 
87812b510759SStefano Zampini   /* free memory */
8782fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
878343371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8784c8587f34SStefano Zampini   PetscFunctionReturn(0);
8785c8587f34SStefano Zampini }
8786674ae819SStefano Zampini 
8787f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8788f34684f1SStefano Zampini {
8789f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8790f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8791f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8792dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8793dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
879473be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8795dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8796f34684f1SStefano Zampini   PetscErrorCode ierr;
8797f34684f1SStefano Zampini 
8798f34684f1SStefano Zampini   PetscFunctionBegin;
8799f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
88006c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8801dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
88023bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8803dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8804dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
88056583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8806dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8807dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8808dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
88096c4ed002SBarry 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);
8810dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8811dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8812*580bdb30SBarry Smith   ierr = PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size);CHKERRQ(ierr);
8813dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8814dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8815f34684f1SStefano Zampini 
8816f34684f1SStefano Zampini   /* check numbering */
8817f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8818019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8819dc456d91SStefano Zampini     PetscInt    i;
8820b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8821f34684f1SStefano Zampini 
8822f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8823f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8824f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
88251575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8826019a44ceSStefano Zampini     /* counter */
8827019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8828019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8829019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8830019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8831019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8832019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8833f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8834f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8835727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8836f34684f1SStefano Zampini     }
8837f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8838f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8839f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8840e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8841e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8842e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8843e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8844f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8845019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8846f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8847019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
88482c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
884975c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8850b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
88512c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
88526080607fSStefano 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);
8853f34684f1SStefano Zampini       }
8854f34684f1SStefano Zampini     }
8855019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8856b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8857f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8858f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8859f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8860f34684f1SStefano Zampini     }
8861f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8862f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8863e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8864e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8865f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
88666080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %D (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8867b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8868ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8869ca8b9ea9SStefano Zampini 
8870ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
88713bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8872f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8873f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8874f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8875f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
88766080607fSStefano 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);
8877f34684f1SStefano Zampini       }
8878f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8879ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8880f34684f1SStefano Zampini     }
8881f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
88821575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8883302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8884f34684f1SStefano Zampini   }
88856080607fSStefano Zampini 
8886f34684f1SStefano Zampini   /* get back data */
8887f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8888f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8889674ae819SStefano Zampini   PetscFunctionReturn(0);
8890674ae819SStefano Zampini }
8891674ae819SStefano Zampini 
8892a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8893e456f2a8SStefano Zampini {
8894e456f2a8SStefano Zampini   IS             localis_t;
8895a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8896e456f2a8SStefano Zampini   PetscScalar    *vals;
8897e456f2a8SStefano Zampini   PetscErrorCode ierr;
8898e456f2a8SStefano Zampini 
8899e456f2a8SStefano Zampini   PetscFunctionBegin;
8900a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8901e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8902854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8903e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8904e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8905a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8906a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
89071035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
89083151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8909a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
89101035eff8SStefano Zampini   }
8911a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8912e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8913e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8914a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8915a7dc3881SStefano Zampini   /* now compute set in local ordering */
8916a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8917a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8918a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8919a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8920a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8921ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8922e456f2a8SStefano Zampini       lsize++;
8923e456f2a8SStefano Zampini     }
8924e456f2a8SStefano Zampini   }
8925854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8926a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8927ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8928e456f2a8SStefano Zampini       idxs[lsize++] = i;
8929e456f2a8SStefano Zampini     }
8930e456f2a8SStefano Zampini   }
8931a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8932a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8933e456f2a8SStefano Zampini   *localis = localis_t;
8934e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8935e456f2a8SStefano Zampini }
8936906d46d4SStefano Zampini 
893708122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8938b96c3477SStefano Zampini {
8939a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8940b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8941b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8942a64f4aa4SStefano Zampini   Mat                 S_j;
8943b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8944b96c3477SStefano Zampini   PetscBool           free_used_adj;
8945b96c3477SStefano Zampini   PetscErrorCode      ierr;
8946b96c3477SStefano Zampini 
8947b96c3477SStefano Zampini   PetscFunctionBegin;
894843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8949b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8950b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
895108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8952b96c3477SStefano Zampini     used_xadj = NULL;
8953b96c3477SStefano Zampini     used_adjncy = NULL;
8954b96c3477SStefano Zampini   } else {
895508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
895608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
895708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
895808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8959b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8960b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8961b96c3477SStefano Zampini     } else {
89622fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8963b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8964b96c3477SStefano Zampini       PetscInt       nvtxs;
8965b96c3477SStefano Zampini 
89662fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
89672fffb893SStefano Zampini       if (flg_row) {
8968b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8969*580bdb30SBarry Smith         ierr = PetscArraycpy(used_xadj,xadj,nvtxs+1);CHKERRQ(ierr);
8970*580bdb30SBarry Smith         ierr = PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
8971b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
89722fffb893SStefano Zampini       } else {
89732fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
89742fffb893SStefano Zampini         used_xadj = NULL;
89752fffb893SStefano Zampini         used_adjncy = NULL;
89762fffb893SStefano Zampini       }
89772fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8978b96c3477SStefano Zampini     }
8979b96c3477SStefano Zampini   }
8980d5574798SStefano Zampini 
8981d5574798SStefano Zampini   /* setup sub_schurs data */
89822f37b69bSStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8983df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8984df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8985a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
898691af6908SStefano 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);
8987a64f4aa4SStefano Zampini   } else {
898872b8c272SStefano Zampini     Mat       change = NULL;
89899d54b7f4SStefano Zampini     Vec       scaling = NULL;
8990111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8991111315fdSstefano_zampini     PetscInt  benign_n;
8992111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8993111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8994111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8995a3df083aSStefano Zampini 
89965feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
89975feab87aSStefano Zampini       PetscInt n_vertices;
89985feab87aSStefano Zampini 
89995feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
90002034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
90015feab87aSStefano Zampini     }
900204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
900304708bb6SStefano Zampini     if (!isseqaij) {
900404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
900504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
900604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
900704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
900804708bb6SStefano Zampini       } else {
9009511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
901004708bb6SStefano Zampini       }
901104708bb6SStefano Zampini     }
9012a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
9013a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
9014ca92afb2SStefano Zampini     } else {
9015a3df083aSStefano Zampini       benign_n = 0;
9016ca92afb2SStefano Zampini     }
9017b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
9018b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
9019b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
902072b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
902122db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
9022b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
902322db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
9024b7ab4a40SStefano Zampini     }
9025b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
9026b7ab4a40SStefano 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 */
9027b7ab4a40SStefano Zampini     if (need_change) {
902888c03ad3SStefano Zampini       PC_IS   *pcisf;
902988c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
903088c03ad3SStefano Zampini       PC      pcf;
903188c03ad3SStefano Zampini 
9032e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
903388c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
903488c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
903588c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
9036b9be95fcSstefano_zampini 
903788c03ad3SStefano Zampini       /* hacks */
903888c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
903972b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
904072b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
904172b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
904272b8c272SStefano Zampini       pcisf->n                     = pcis->n;
904372b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
904488c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
904588c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
904688c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
904788c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
904888c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
904988c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
905072b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
905188c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
9052b9be95fcSstefano_zampini 
9053b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
905488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
905572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
905672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
905772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
905872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
9059b9be95fcSstefano_zampini 
906088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
906172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
906288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
906388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
906488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
906588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
906688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
906788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
9068b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
906988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
907088c03ad3SStefano Zampini     }
90719d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
9072111315fdSstefano_zampini 
9073111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
9074111315fdSstefano_zampini     if (iP) {
9075111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
9076111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
9077111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
9078111315fdSstefano_zampini     }
9079111315fdSstefano_zampini     if (discrete_harmonic) {
9080111315fdSstefano_zampini       Mat A;
9081111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
9082111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
9083111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
9084111315fdSstefano_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);
9085111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
9086111315fdSstefano_zampini     } else {
908791af6908SStefano 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);
9088111315fdSstefano_zampini     }
908972b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
909072b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
9091ca92afb2SStefano Zampini   }
9092d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9093b96c3477SStefano Zampini 
9094b96c3477SStefano Zampini   /* free adjacency */
9095b96c3477SStefano Zampini   if (free_used_adj) {
9096b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
9097b96c3477SStefano Zampini   }
909843371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
9099b96c3477SStefano Zampini   PetscFunctionReturn(0);
9100b96c3477SStefano Zampini }
9101b96c3477SStefano Zampini 
910208122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
9103b96c3477SStefano Zampini {
9104b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9105b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9106b96c3477SStefano Zampini   PCBDDCGraph         graph;
9107b96c3477SStefano Zampini   PetscErrorCode      ierr;
9108b96c3477SStefano Zampini 
9109b96c3477SStefano Zampini   PetscFunctionBegin;
9110b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
911108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
91123301b35fSStefano Zampini     IS       verticesIS,verticescomm;
91133301b35fSStefano Zampini     PetscInt vsize,*idxs;
9114b96c3477SStefano Zampini 
9115b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
91163301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
91173301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
91183301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
91193301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
9120c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
9121b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
9122be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
9123441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
91243301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
9125b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
9126b96c3477SStefano Zampini   } else {
9127b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
9128b96c3477SStefano Zampini   }
9129e4d548c7SStefano Zampini   /* print some info */
91305c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
9131e4d548c7SStefano Zampini     IS       vertices;
9132e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
9133c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
9134e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9135e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
9136e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9137e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
91386080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,(int)nv,pcbddc->use_vertices);CHKERRQ(ierr);
91396080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,(int)nedges,pcbddc->use_edges);CHKERRQ(ierr);
91406080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,(int)nfaces,pcbddc->use_faces);CHKERRQ(ierr);
9141e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
9142e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9143c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9144e4d548c7SStefano Zampini   }
9145b96c3477SStefano Zampini 
9146b96c3477SStefano Zampini   /* sub_schurs init */
9147b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
9148b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
9149b334f244SStefano Zampini   }
915088113c35SStefano 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);
9151a64f4aa4SStefano Zampini 
9152b96c3477SStefano Zampini   /* free graph struct */
915308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
9154b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
9155b96c3477SStefano Zampini   }
9156b96c3477SStefano Zampini   PetscFunctionReturn(0);
9157b96c3477SStefano Zampini }
9158fa34dd3eSStefano Zampini 
9159fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
9160fa34dd3eSStefano Zampini {
9161fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9162fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9163fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
9164fa34dd3eSStefano Zampini 
9165fa34dd3eSStefano Zampini   PetscFunctionBegin;
9166fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
9167fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
91684f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
9169fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
91704f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
917175c01103SStefano Zampini     PetscReal      norm;
9172fa34dd3eSStefano Zampini     PetscInt       i;
9173fa34dd3eSStefano Zampini 
9174fa34dd3eSStefano Zampini     /* B0 and B0_B */
9175fa34dd3eSStefano Zampini     if (zerodiag) {
9176fa34dd3eSStefano Zampini       IS       dummy;
9177fa34dd3eSStefano Zampini 
91784f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
91797dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
9180fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
9181fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
9182fa34dd3eSStefano Zampini     }
9183fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
9184fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
9185fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
9186fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9187fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9188fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9189fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9190fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
9191fa34dd3eSStefano Zampini     /* S_j */
91922f37b69bSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
9193fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
9194fa34dd3eSStefano Zampini 
9195fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
9196fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
9197fa34dd3eSStefano Zampini     /* continuous in primal space */
9198fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
9199fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9200fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9201fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
92024f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
92034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
9204fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9205fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9206fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9207fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9208fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9209fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9210fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
9211fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
9212fa34dd3eSStefano Zampini 
9213fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
9214fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
9215fa34dd3eSStefano Zampini     /* local with Schur */
9216fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
9217fa34dd3eSStefano Zampini     if (zerodiag) {
9218fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
92194f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
9220fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9221fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
9222fa34dd3eSStefano Zampini     }
9223fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
9224fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9225fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9226fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9227fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9228fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
9229fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9230fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9231fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
9232fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9233fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9234fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9235fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9236fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9237fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
9238fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
9239fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9240fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9241fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9242fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9243fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9244fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9245fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9246fa34dd3eSStefano Zampini     if (zerodiag) {
9247fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
9248fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
92494f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
9250fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9251fa34dd3eSStefano Zampini     }
9252fa34dd3eSStefano Zampini     /* BDDC */
9253fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
9254fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
9255fa34dd3eSStefano Zampini 
9256fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
9257fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
9258fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
92596080607fSStefano Zampini     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);CHKERRQ(ierr);
92604f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
92616080607fSStefano 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);
9262fa34dd3eSStefano Zampini     }
92634f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
9264fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
9265fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
9266fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
9267fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9268fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
9269fa34dd3eSStefano Zampini   }
9270fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9271fa34dd3eSStefano Zampini }
92721e0482f5SStefano Zampini 
92731e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
92741e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
92751e0482f5SStefano Zampini {
92761e0482f5SStefano Zampini   Mat            At;
92771e0482f5SStefano Zampini   IS             rows;
92781e0482f5SStefano Zampini   PetscInt       rst,ren;
92791e0482f5SStefano Zampini   PetscErrorCode ierr;
92801e0482f5SStefano Zampini   PetscLayout    rmap;
92811e0482f5SStefano Zampini 
92821e0482f5SStefano Zampini   PetscFunctionBegin;
92831e0482f5SStefano Zampini   rst = ren = 0;
92841e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
92851e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
92861e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
92871e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
92881e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
92891e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
92901e0482f5SStefano Zampini   }
9291e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
92927dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
92931e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
92941e0482f5SStefano Zampini 
92951e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
92961e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
92971e0482f5SStefano Zampini     IS         from,to;
92981e0482f5SStefano Zampini     Vec        gvec;
92991e0482f5SStefano Zampini     PetscInt   lsize;
93001e0482f5SStefano Zampini 
93011e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
93021e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
93031e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
93041e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
93051e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
93061e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
93071e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
93081e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
93091e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
93101e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
93111e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
93121e0482f5SStefano Zampini     b->A = a->A;
93131e0482f5SStefano Zampini     b->B = a->B;
93141e0482f5SStefano Zampini 
93151e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
93161e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
93171e0482f5SStefano Zampini     b->rowindices      = 0;
93181e0482f5SStefano Zampini     b->rowvalues       = 0;
93191e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
93201e0482f5SStefano Zampini 
93211e0482f5SStefano Zampini     (*B)->rmap         = rmap;
93221e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
93231e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
93241e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
93251e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
93261e0482f5SStefano Zampini 
93271e0482f5SStefano Zampini     if (a->colmap) {
93281e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
93291e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
93301e0482f5SStefano Zampini #else
93311e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
93321e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
9333*580bdb30SBarry Smith       ierr = PetscArraycpy(b->colmap,a->colmap,At->cmap->N);CHKERRQ(ierr);
93341e0482f5SStefano Zampini #endif
93351e0482f5SStefano Zampini     } else b->colmap = 0;
93361e0482f5SStefano Zampini     if (a->garray) {
93371e0482f5SStefano Zampini       PetscInt len;
93381e0482f5SStefano Zampini       len  = a->B->cmap->n;
93391e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
93401e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
9341*580bdb30SBarry Smith       if (len) { ierr = PetscArraycpy(b->garray,a->garray,len);CHKERRQ(ierr); }
93421e0482f5SStefano Zampini     } else b->garray = 0;
93431e0482f5SStefano Zampini 
93441e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
93451e0482f5SStefano Zampini     b->lvec = a->lvec;
93461e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
93471e0482f5SStefano Zampini 
93481e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
93491e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
93501e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
93511e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
93521e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
93539448b7f1SJunchao Zhang     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
93541e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
93551e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
93561e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
93571e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
93581e0482f5SStefano Zampini   }
93591e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
93601e0482f5SStefano Zampini   PetscFunctionReturn(0);
93611e0482f5SStefano Zampini }
9362