xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 075e25bc30b466bd3ec0474b24a498e2df9bf8a8)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h>
5c80a6c00SStefano Zampini #include <petscdmplex.h>
6674ae819SStefano Zampini #include <petscblaslapack.h>
7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h>
97620a527SStefano Zampini #include <petscdmda.h>
10674ae819SStefano Zampini 
111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
121e0482f5SStefano Zampini 
13f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
14f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
16a13144ffSStefano Zampini {
17a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
18a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
19a13144ffSStefano Zampini   PetscReal      *sing;
20a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
21a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
22a13144ffSStefano Zampini   PetscErrorCode ierr;
23a13144ffSStefano Zampini 
24a13144ffSStefano Zampini   PetscFunctionBegin;
25a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
26a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
27614dbb09SStefano Zampini #else
28a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
29a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
30a13144ffSStefano Zampini 
31a13144ffSStefano Zampini   /* workspace */
32a13144ffSStefano Zampini   if (!work) {
33a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
34f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
35a13144ffSStefano Zampini   } else {
36a13144ffSStefano Zampini     ulw   = lw;
37a13144ffSStefano Zampini     uwork = work;
38a13144ffSStefano Zampini   }
39a13144ffSStefano Zampini   n = PetscMin(nr,nc);
40a13144ffSStefano Zampini   if (!rwork) {
41a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
42a13144ffSStefano Zampini   } else {
43a13144ffSStefano Zampini     sing = rwork;
44a13144ffSStefano Zampini   }
45a13144ffSStefano Zampini 
46a13144ffSStefano Zampini   /* SVD */
47a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
55a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
56a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
57a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
58a13144ffSStefano Zampini   if (!rwork) {
59a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   if (!work) {
62a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
63a13144ffSStefano Zampini   }
64a13144ffSStefano Zampini   /* create B */
65f498cd09SStefano Zampini   if (!range) {
66a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
67a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
68a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
69f498cd09SStefano Zampini   } else {
70f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
71f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
72f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
73f498cd09SStefano Zampini   }
74a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
75a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
76614dbb09SStefano Zampini #endif
77614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
78a13144ffSStefano Zampini   PetscFunctionBegin;
79a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
80a13144ffSStefano Zampini #endif
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1237dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
156a13144ffSStefano Zampini {
157a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
158a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1590569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
160eee23b56SStefano Zampini   Vec                    tvec;
161a13144ffSStefano Zampini   PetscSF                sfv;
1621e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
163a13144ffSStefano Zampini   MPI_Comm               comm;
164c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
165c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1667d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
167a13144ffSStefano Zampini   PetscScalar            *vals,*work;
168a13144ffSStefano Zampini   PetscReal              *rwork;
169a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1701e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
171a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
172eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
173b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
174a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
175b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
176637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
177b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179b03ebc13SStefano Zampini #endif
180213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
181a13144ffSStefano Zampini   PetscErrorCode         ierr;
182a13144ffSStefano Zampini 
183a13144ffSStefano Zampini   PetscFunctionBegin;
184213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
185213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
186213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
187213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
188213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
189213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
190213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
191213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
192a13144ffSStefano Zampini   print      = PETSC_FALSE;
193213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
194a13144ffSStefano Zampini 
195213b8bfaSStefano Zampini   /* Command line customization */
196213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
201213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
202213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203213b8bfaSStefano Zampini 
204213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2051e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2061e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   if (!singular) {
209a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
210a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
211c2151214SStefano Zampini     for (i=0;i<n;i++) {
212a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
213a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
214a13144ffSStefano Zampini         break;
215a13144ffSStefano Zampini       }
216a13144ffSStefano Zampini     }
217a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
219a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
220213b8bfaSStefano Zampini   }
221a13144ffSStefano Zampini 
222213b8bfaSStefano Zampini   /* Get Nedelec field */
2236080607fSStefano 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);
224213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
225c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
226c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
227c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
228213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
229213b8bfaSStefano Zampini     ne            = n;
230213b8bfaSStefano Zampini     nedfieldlocal = NULL;
231213b8bfaSStefano Zampini     global        = PETSC_TRUE;
232213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
233213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
234213b8bfaSStefano Zampini 
235213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
236213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
237213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
238213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
239213b8bfaSStefano Zampini       PetscInt nc;
240213b8bfaSStefano Zampini 
241213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
242213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
243213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
244213b8bfaSStefano Zampini     }
245213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
246213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
248213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
249213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
250213b8bfaSStefano Zampini   } else {
251213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
252213b8bfaSStefano Zampini   }
253213b8bfaSStefano Zampini 
254213b8bfaSStefano Zampini   /* Sanity checks */
255213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
256213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
2576080607fSStefano 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);
258213b8bfaSStefano Zampini 
259213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2601e0482f5SStefano Zampini   if (setprimal) {
261eee23b56SStefano Zampini     IS       enedfieldlocal;
262eee23b56SStefano Zampini     PetscInt *eidxs;
263eee23b56SStefano Zampini 
264eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
265eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
266213b8bfaSStefano Zampini     if (nedfieldlocal) {
267213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
268eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
269eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
270eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
271eee23b56SStefano Zampini         }
272eee23b56SStefano Zampini       }
273eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
274213b8bfaSStefano Zampini     } else {
275213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
276213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
277213b8bfaSStefano Zampini           eidxs[cum++] = i;
278213b8bfaSStefano Zampini         }
279213b8bfaSStefano Zampini       }
280213b8bfaSStefano Zampini     }
281213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
282eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2851e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
286eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2871e0482f5SStefano Zampini     PetscFunctionReturn(0);
2881e0482f5SStefano Zampini   }
289a13144ffSStefano Zampini 
290213b8bfaSStefano Zampini   /* Compute some l2g maps */
291213b8bfaSStefano Zampini   if (nedfieldlocal) {
292c2151214SStefano Zampini     IS is;
293c2151214SStefano Zampini 
294c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
295c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2961e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2971e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2981e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
2991e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
3001e0482f5SStefano Zampini     if (global) {
3011e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3021e0482f5SStefano Zampini       el2g = al2g;
3031e0482f5SStefano Zampini     } else {
3041e0482f5SStefano Zampini       IS gis;
3051e0482f5SStefano Zampini 
3061e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3071e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3081e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3091e0482f5SStefano Zampini     }
310c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
311c2151214SStefano Zampini   } else {
3121e0482f5SStefano Zampini     /* restore default */
3131e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3141e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3151e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3161e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3171e0482f5SStefano Zampini     el2g = al2g;
318c2151214SStefano Zampini     fl2g = NULL;
319c2151214SStefano Zampini   }
320a13144ffSStefano Zampini 
321213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
322c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
323c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
324c2151214SStefano Zampini   if (nedfieldlocal) {
325c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
326c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
327c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
328c2151214SStefano Zampini   } else {
329c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
330c2151214SStefano Zampini   }
331c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
332c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333213b8bfaSStefano Zampini 
334213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
335213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
336213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3371e0482f5SStefano Zampini     if (global) {
3381e0482f5SStefano Zampini       PetscInt rst;
3391e0482f5SStefano Zampini 
340c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
341c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
342c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
343c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
344c2151214SStefano Zampini         }
345c2151214SStefano Zampini       }
346a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
347c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3481e0482f5SStefano Zampini     } else {
3491e0482f5SStefano Zampini       PetscInt *tbz;
3501e0482f5SStefano Zampini 
3511e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3521e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3561e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3571e0482f5SStefano Zampini           tbz[cum++] = i;
3581e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3591e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3621e0482f5SStefano Zampini     }
363213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
364213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
365213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
366213b8bfaSStefano Zampini   }
367a13144ffSStefano Zampini 
368a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
369a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
370a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3717dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
372a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
377a13144ffSStefano Zampini 
378213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
379c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
380a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
387213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
388213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
389a13144ffSStefano Zampini 
3901e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
391213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
392a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
393213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
394a13144ffSStefano Zampini 
395213b8bfaSStefano Zampini   if (print) {
396213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
397213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
398213b8bfaSStefano Zampini   }
399213b8bfaSStefano Zampini 
400213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4010569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4020569b399SStefano Zampini 
403a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4044e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4054e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
406a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4097d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
410c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
411a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
412a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
413a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
414c2151214SStefano Zampini     IS is;
415c2151214SStefano Zampini 
416c2151214SStefano Zampini     if (fl2g) {
417c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
418c2151214SStefano Zampini     } else {
419c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
420c2151214SStefano Zampini     }
421c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
422c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
423a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
424a13144ffSStefano Zampini       if (idxs[i] >= 0) {
425a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4267d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
427a13144ffSStefano Zampini       }
428a13144ffSStefano Zampini     }
429c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
430c2151214SStefano Zampini     if (fl2g) {
431c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
432c2151214SStefano Zampini     }
433a13144ffSStefano Zampini   }
434a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
435c2151214SStefano Zampini     IS is;
436c2151214SStefano Zampini 
437c2151214SStefano Zampini     if (fl2g) {
438c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
439c2151214SStefano Zampini     } else {
440c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
441c2151214SStefano Zampini     }
442c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
443c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
444a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
445a13144ffSStefano Zampini       if (idxs[i] >= 0) {
446a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
447a13144ffSStefano Zampini       }
448a13144ffSStefano Zampini     }
449c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
450c2151214SStefano Zampini     if (fl2g) {
451c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
452a13144ffSStefano Zampini     }
453c2151214SStefano Zampini   }
454c2151214SStefano Zampini 
455213b8bfaSStefano Zampini   /* Count neighs per dof */
456b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
457b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
458637e8532SStefano Zampini 
4597d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4607d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
46162b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
46262b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
463b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
46462b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
46562b0c6f7SStefano Zampini     }
46662b0c6f7SStefano Zampini   }
467637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
46862b0c6f7SStefano Zampini   if (!conforming) {
46962b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
47062b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
47162b0c6f7SStefano Zampini   }
4724e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
473dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
47462b0c6f7SStefano Zampini   cum  = 0;
475a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
476dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47762b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
478a13144ffSStefano Zampini       marks[cum++] = i;
479dec27d64SStefano Zampini       continue;
480dec27d64SStefano Zampini     }
481dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
48262b0c6f7SStefano Zampini     if (!conforming) {
48362b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
484a13144ffSStefano Zampini         marks[cum++] = i;
485a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
486a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
487a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
488a13144ffSStefano Zampini         }
48962b0c6f7SStefano Zampini       } else {
49062b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
49162b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
49262b0c6f7SStefano Zampini            - at most 2 endpoints
49362b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49462b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49562b0c6f7SStefano Zampini         */
49662b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49762b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49862b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
49962b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
50062b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
50162b0c6f7SStefano Zampini           if (nconn > order) ends++;
50262b0c6f7SStefano Zampini           else if (nconn == order) ints++;
50362b0c6f7SStefano Zampini           else undef++;
50462b0c6f7SStefano Zampini         }
50562b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50662b0c6f7SStefano Zampini           marks[cum++] = i;
50762b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
50862b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
50962b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
51062b0c6f7SStefano Zampini           }
51162b0c6f7SStefano Zampini         }
51262b0c6f7SStefano Zampini       }
513a13144ffSStefano Zampini     }
514dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
515dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
516dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
517dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
518a13144ffSStefano Zampini     }
519dec27d64SStefano Zampini   }
52062b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
521dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5224e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
52362b0c6f7SStefano Zampini   if (!conforming) {
52462b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52562b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
52662b0c6f7SStefano Zampini   }
5274e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
528637e8532SStefano Zampini 
529b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5304e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
531a13144ffSStefano Zampini   if (print) {
5324e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5334e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5344e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
535a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
536a13144ffSStefano Zampini   }
537a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
538dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
539a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
540637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5417d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
542b03ebc13SStefano Zampini     if (!order) { /* variable order */
543dec27d64SStefano Zampini       PetscReal vorder = 0.;
544dec27d64SStefano Zampini 
545dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
546dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
5476080607fSStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%D)",vorder,test);
548dec27d64SStefano Zampini       ord  = 1;
549dec27d64SStefano Zampini     }
550a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
5516080607fSStefano 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);
552a13144ffSStefano Zampini #endif
553637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5547d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5557d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5567d871cd7SStefano Zampini         break;
5577d871cd7SStefano Zampini       }
558637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
559637e8532SStefano Zampini         sneighs = PETSC_FALSE;
560637e8532SStefano Zampini       } else {
561637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
562637e8532SStefano Zampini         for (k=0;k<vc;k++) {
563637e8532SStefano Zampini           if (vn[k] != en[k]) {
564637e8532SStefano Zampini             sneighs = PETSC_FALSE;
565637e8532SStefano Zampini             break;
566637e8532SStefano Zampini           }
567637e8532SStefano Zampini         }
568637e8532SStefano Zampini       }
569637e8532SStefano Zampini     }
5707d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5716080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %D (%D %D %D)\n",i,!sneighs,test >= 3*ord,bdir);
572a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
573dec27d64SStefano Zampini     } else if (test == ord) {
574b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
5756080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %D\n",i);
576a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
577a13144ffSStefano Zampini       } else {
5786080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %D\n",i);
579a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
580a13144ffSStefano Zampini       }
581a13144ffSStefano Zampini     }
582a13144ffSStefano Zampini   }
583b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
584b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
5857d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
586b03ebc13SStefano Zampini 
587b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
588b03ebc13SStefano Zampini   if (order != 1) {
589b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
590b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
591b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
592b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
593b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
594b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
595b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
596b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
597b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
598b03ebc13SStefano Zampini             PetscInt v = jjt[k];
599b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
600b03ebc13SStefano Zampini               found = PETSC_TRUE;
601b03ebc13SStefano Zampini               break;
602b03ebc13SStefano Zampini             }
603b03ebc13SStefano Zampini           }
604b03ebc13SStefano Zampini         }
605b03ebc13SStefano Zampini         if (!found) {
6066080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D CLEARED\n",i);
607b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
608b03ebc13SStefano Zampini         } else {
6096080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D ACCEPTED\n",i);
610b03ebc13SStefano Zampini         }
611b03ebc13SStefano Zampini       }
612b03ebc13SStefano Zampini     }
613b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
614b03ebc13SStefano Zampini   }
615dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
616a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
617b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
618a13144ffSStefano Zampini 
619a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6200569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
621a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6224e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
623a13144ffSStefano Zampini 
6244e64d54eSstefano_zampini   /* Mark interior nodal dofs */
625a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6264e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
627a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
628a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6294e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
630a13144ffSStefano Zampini     }
631a13144ffSStefano Zampini   }
632a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
633a13144ffSStefano Zampini 
634a13144ffSStefano Zampini   /* communicate corners and splitpoints */
635a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
636a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
637a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
638a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
639a13144ffSStefano Zampini 
640a13144ffSStefano Zampini   if (print) {
641a13144ffSStefano Zampini     IS tbz;
642a13144ffSStefano Zampini 
643a13144ffSStefano Zampini     cum = 0;
644a13144ffSStefano Zampini     for (i=0;i<nv;i++)
645a13144ffSStefano Zampini       if (sfvleaves[i])
646a13144ffSStefano Zampini         vmarks[cum++] = i;
647a13144ffSStefano Zampini 
648a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
649a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
650a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
651a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
652a13144ffSStefano Zampini   }
653a13144ffSStefano Zampini 
654a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
655a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
656a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
657a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
658a13144ffSStefano Zampini 
6594e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6604e64d54eSstefano_zampini      and interior nodal dofs */
661a13144ffSStefano Zampini   cum = 0;
662a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
663a13144ffSStefano Zampini     if (sfvleaves[i]) {
664a13144ffSStefano Zampini       vmarks[cum++] = i;
665a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
666a13144ffSStefano Zampini     }
6674e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
668a13144ffSStefano Zampini   }
6694e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
670a13144ffSStefano Zampini   if (print) {
671a13144ffSStefano Zampini     IS tbz;
672a13144ffSStefano Zampini 
673a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6744e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
675a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
676a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
677a13144ffSStefano Zampini   }
678a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
679a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
680a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
681a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
682a13144ffSStefano Zampini 
683a13144ffSStefano Zampini   /* Recompute G */
684a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
685a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
686a13144ffSStefano Zampini   if (print) {
687a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
688a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
689a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
690a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
691a13144ffSStefano Zampini   }
692a13144ffSStefano Zampini 
693a13144ffSStefano Zampini   /* Get primal dofs (if any) */
694a13144ffSStefano Zampini   cum = 0;
695a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
696a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
697a13144ffSStefano Zampini   }
698c2151214SStefano Zampini   if (fl2g) {
699c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
700c2151214SStefano Zampini   }
701a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
702a13144ffSStefano Zampini   if (print) {
703a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
704a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
705a13144ffSStefano Zampini   }
706a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
707c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
708a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
709a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
710a13144ffSStefano Zampini 
711a13144ffSStefano Zampini   /* Compute edge connectivity */
712a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
713a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
715c2151214SStefano Zampini   if (fl2g) {
716c2151214SStefano Zampini     PetscBT   btf;
717c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
718c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
719c2151214SStefano Zampini 
720c2151214SStefano Zampini     /* create CSR for all local dofs */
721c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
722c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
7236080607fSStefano 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);
724c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
725c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
726c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
727c2151214SStefano Zampini       rest = PETSC_TRUE;
728c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
729c2151214SStefano Zampini     } else {
730c2151214SStefano Zampini       free   = PETSC_TRUE;
731c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
732c2151214SStefano Zampini       iiu[0] = 0;
733c2151214SStefano Zampini       for (i=0;i<n;i++) {
734c2151214SStefano Zampini         iiu[i+1] = i+1;
735c2151214SStefano Zampini         jju[i]   = -1;
736d904f53bSStefano Zampini       }
737c2151214SStefano Zampini     }
738c2151214SStefano Zampini 
739c2151214SStefano Zampini     /* import sizes of CSR */
740c2151214SStefano Zampini     iia[0] = 0;
741c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
742c2151214SStefano Zampini 
743c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
744c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
745c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
746c2151214SStefano Zampini     for (i=0;i<ne;i++) {
747c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
748c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
749c2151214SStefano Zampini     }
750c2151214SStefano Zampini 
751c2151214SStefano Zampini     /* iia in CSR */
752c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
753c2151214SStefano Zampini 
754c2151214SStefano Zampini     /* jja in CSR */
755c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
756c2151214SStefano Zampini     for (i=0;i<n;i++)
757c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
758c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
759c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
760c2151214SStefano Zampini 
761c2151214SStefano Zampini     /* map edge dofs connectivity */
7621e0482f5SStefano Zampini     if (jj) {
763c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
764c2151214SStefano Zampini       for (i=0;i<ne;i++) {
765c2151214SStefano Zampini         PetscInt e = idxs[i];
766c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
767c2151214SStefano Zampini       }
7681e0482f5SStefano Zampini     }
769c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
770c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
771c2151214SStefano Zampini     if (rest) {
772c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
773c2151214SStefano Zampini     }
774c2151214SStefano Zampini     if (free) {
775c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
776c2151214SStefano Zampini     }
777c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
778c2151214SStefano Zampini   } else {
779c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
780c2151214SStefano Zampini   }
781c2151214SStefano Zampini 
782a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
783a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
784213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
785a13144ffSStefano Zampini 
786a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
787c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
788a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
789a13144ffSStefano Zampini 
790c2151214SStefano Zampini   if (fl2g) {
791c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
792c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
793c2151214SStefano Zampini     for (i=0;i<nee;i++) {
794c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
795c2151214SStefano Zampini     }
796c2151214SStefano Zampini   } else {
797c2151214SStefano Zampini     eedges  = alleedges;
798c2151214SStefano Zampini     primals = allprimals;
799c2151214SStefano Zampini   }
800c2151214SStefano Zampini 
801a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
802a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
803c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
804c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
805c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
806c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
807c2151214SStefano Zampini   if (print) {
808c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
809c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
810c2151214SStefano Zampini   }
811c2151214SStefano Zampini 
812c2151214SStefano Zampini   maxsize = 0;
813a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
814a13144ffSStefano Zampini     PetscInt size,mark = i+1;
815a13144ffSStefano Zampini 
816a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
817a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
818a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
819a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
820a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
821a13144ffSStefano Zampini   }
822a13144ffSStefano Zampini 
823a13144ffSStefano Zampini   /* Find coarse edge endpoints */
824a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
825a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
826a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
827a13144ffSStefano Zampini     PetscInt mark = i+1,size;
828a13144ffSStefano Zampini 
829a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8301e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8316080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
832a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
833a13144ffSStefano Zampini     if (print) {
8346080607fSStefano Zampini       ierr = PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %D\n",i);CHKERRQ(ierr);
8356080607fSStefano Zampini       ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
836a13144ffSStefano Zampini     }
837a13144ffSStefano Zampini     for (j=0;j<size;j++) {
838a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
8396080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %D\n",ee);
840a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8416080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %D\n",jj[k]);
842a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
8436080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %D\n",jj[k]);
844a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
845a13144ffSStefano Zampini           PetscInt  k2;
846a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
847a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
8486080607fSStefano 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]));
849c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
850c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
851c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
852a13144ffSStefano Zampini               corner = PETSC_TRUE;
853a13144ffSStefano Zampini               break;
854a13144ffSStefano Zampini             }
855a13144ffSStefano Zampini           }
856a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
8576080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %D\n",jj[k]);
858a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
859a13144ffSStefano Zampini           } else {
860a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
861a13144ffSStefano Zampini           }
862a13144ffSStefano Zampini         }
863a13144ffSStefano Zampini       }
864a13144ffSStefano Zampini     }
865a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
866a13144ffSStefano Zampini   }
867a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
868a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
869c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
870a13144ffSStefano Zampini 
871a13144ffSStefano Zampini   /* Reset marked primal dofs */
872a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
873a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
874a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
875a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
876a13144ffSStefano Zampini 
8770569b399SStefano Zampini   /* Now use the initial lG */
8780569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8790569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8800569b399SStefano Zampini   lG   = lGinit;
8810569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8820569b399SStefano Zampini 
883a13144ffSStefano Zampini   /* Compute extended cols indices */
884b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
885b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
886a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
887a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
888a13144ffSStefano Zampini   i   *= maxsize;
889b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
890a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
891a13144ffSStefano Zampini   eerr = PETSC_FALSE;
892a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
893b03ebc13SStefano Zampini     PetscInt size,found = 0;
894a13144ffSStefano Zampini 
895a13144ffSStefano Zampini     cum  = 0;
896a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8971e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8986080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
899a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
900b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
901a13144ffSStefano Zampini     for (j=0;j<size;j++) {
902a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
903b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
904b03ebc13SStefano Zampini         PetscInt vv = jj[k];
905b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
906b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
907b03ebc13SStefano Zampini       }
908a13144ffSStefano Zampini     }
909a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
910a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
911a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
912a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
913a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
914a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
915a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
916b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
917b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
918a13144ffSStefano Zampini       if (print) {
919a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
920a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
921a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
922a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
923a13144ffSStefano Zampini       }
924a13144ffSStefano Zampini       eerr = PETSC_TRUE;
925a13144ffSStefano Zampini     }
926a13144ffSStefano Zampini   }
9274e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
928a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
929a13144ffSStefano Zampini   if (done) {
930a13144ffSStefano Zampini     PetscInt *newprimals;
931a13144ffSStefano Zampini 
932a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
933a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
934a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
935a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
936a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9370569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
9386080607fSStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %D)\n",eerr);
939a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
940b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
941b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
942a13144ffSStefano Zampini         PetscInt size,mark = i+1;
943a13144ffSStefano Zampini 
944a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
945a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
946c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
947a13144ffSStefano Zampini         for (j=0;j<size;j++) {
948a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
9496080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %D [%D %D)\n",ee,ii[ee],ii[ee+1]);
950a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
951a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
952a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
953a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
954b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
9556080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %D\n",vv);
956a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
957a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
958a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
959a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
960a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
9616080607fSStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %D\n",ee2);
962a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
963a13144ffSStefano Zampini                   /* finally set the new corners */
964a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
9656080607fSStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %D\n",jj[k3]);
966a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
967a13144ffSStefano Zampini                   }
968a13144ffSStefano Zampini                 }
969a13144ffSStefano Zampini               }
970b03ebc13SStefano Zampini             } else {
9716080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %D\n",jj[k]);
972a13144ffSStefano Zampini             }
973a13144ffSStefano Zampini           }
974a13144ffSStefano Zampini         }
975b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
976b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
977b03ebc13SStefano Zampini 
978b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
9796080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %D\n",i);
980b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
981b03ebc13SStefano Zampini             PetscInt k2;
9826080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %D\n",jj[k]);
983b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
984b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
985b03ebc13SStefano Zampini           }
986b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
987b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
9886080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %D\n",idxs[j]);
989b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
990b03ebc13SStefano Zampini             }
991b03ebc13SStefano Zampini           }
992b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
993b03ebc13SStefano Zampini         }
994a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
995a13144ffSStefano Zampini       }
996a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
997a13144ffSStefano Zampini     }
998b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
9990569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1000a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1001c2151214SStefano Zampini     if (fl2g) {
1002c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1003c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1004c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1005c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1006c2151214SStefano Zampini       }
1007c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1008c2151214SStefano Zampini     }
1009c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1010a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1011a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1012a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1013a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1014a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1015213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1016c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1017c2151214SStefano Zampini     if (fl2g) {
1018c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1019c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1020c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1021c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1022c2151214SStefano Zampini       }
1023c2151214SStefano Zampini     } else {
1024c2151214SStefano Zampini       eedges  = alleedges;
1025c2151214SStefano Zampini       primals = allprimals;
1026c2151214SStefano Zampini     }
1027b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1028a13144ffSStefano Zampini 
1029a13144ffSStefano Zampini     /* Mark again */
1030a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1031a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1032a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1033a13144ffSStefano Zampini 
1034a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1035a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1036a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1037a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1038a13144ffSStefano Zampini     }
1039a13144ffSStefano Zampini     if (print) {
1040a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1041a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1042a13144ffSStefano Zampini     }
1043a13144ffSStefano Zampini 
1044a13144ffSStefano Zampini     /* Recompute extended cols */
1045a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1046a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1047a13144ffSStefano Zampini       PetscInt size;
1048a13144ffSStefano Zampini 
1049a13144ffSStefano Zampini       cum  = 0;
1050a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10511e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10526080607fSStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
1053a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1054a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1055a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10561e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1057a13144ffSStefano Zampini       }
1058a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1059a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1060a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1061a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1062a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1063a13144ffSStefano Zampini       if (cum != size -1) {
1064a13144ffSStefano Zampini         if (print) {
1065a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1066a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1067a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1068a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1069a13144ffSStefano Zampini         }
1070a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1071a13144ffSStefano Zampini       }
1072a13144ffSStefano Zampini     }
1073a13144ffSStefano Zampini   }
1074a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1075a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1076b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
10777d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1078a13144ffSStefano Zampini   /* an error should not occur at this point */
1079a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1080a13144ffSStefano Zampini 
10814e64d54eSstefano_zampini   /* Check the number of endpoints */
10820569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1083b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1084b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10854e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1086b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10874e64d54eSstefano_zampini 
1088b03ebc13SStefano Zampini     /* init with defaults */
1089b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10904e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10911e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10926080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
10934e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1094b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
10954e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10964e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10974e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10984e64d54eSstefano_zampini         PetscInt vv = jj[k];
10994e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
11006080607fSStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %D",i);
1101b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11024e64d54eSstefano_zampini         }
11034e64d54eSstefano_zampini       }
11044e64d54eSstefano_zampini     }
1105b03ebc13SStefano Zampini     if (found != 2) {
1106b03ebc13SStefano Zampini       PetscInt e;
1107b03ebc13SStefano Zampini       if (fl2g) {
1108b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1109b03ebc13SStefano Zampini       } else {
1110b03ebc13SStefano Zampini         e = idxs[0];
1111b03ebc13SStefano Zampini       }
11126080607fSStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %D corners for edge %D (astart %D, estart %D)",found,i,e,idxs[0]);
1113b03ebc13SStefano Zampini     }
1114eee23b56SStefano Zampini 
1115eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1116b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1117b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1118b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1119b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1120b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1121b03ebc13SStefano Zampini     }
1122eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11234e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
11246080607fSStefano 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]);
11254e64d54eSstefano_zampini   }
11260569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11274e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11284e64d54eSstefano_zampini 
1129a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1130a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1131a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1132a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1133a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1134a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1135a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1136a13144ffSStefano Zampini 
1137a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1138a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1139a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1140a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1141a13144ffSStefano Zampini       if (emax < emarks[j]) {
1142a13144ffSStefano Zampini         emax = emarks[j];
1143a13144ffSStefano Zampini         eemax = j;
1144a13144ffSStefano Zampini       }
1145a13144ffSStefano Zampini     }
1146a13144ffSStefano Zampini     /* not relevant for edges */
1147a13144ffSStefano Zampini     if (!eemax) continue;
1148a13144ffSStefano Zampini 
1149a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1150a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
11516080607fSStefano 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]);
1152a13144ffSStefano Zampini       }
1153a13144ffSStefano Zampini     }
1154a13144ffSStefano Zampini   }
1155a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1156a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1157a13144ffSStefano Zampini #endif
1158a13144ffSStefano Zampini 
1159a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1160a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1161a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1162a13144ffSStefano Zampini   extmem *= maxsize;
1163a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1164a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1165a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1166a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1167a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1168213b8bfaSStefano Zampini 
1169a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1170a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1171a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1172a13144ffSStefano Zampini         mark = marks[jj[j]];
1173a13144ffSStefano Zampini 
1174a13144ffSStefano Zampini     /* not relevant */
1175a13144ffSStefano Zampini     if (!mark) continue;
1176a13144ffSStefano Zampini 
1177a13144ffSStefano Zampini     /* import extended row */
1178a13144ffSStefano Zampini     mark--;
1179a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1180a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
11816080607fSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %D > %D",extrowcum[mark] + size,extmem);
1182a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1183a13144ffSStefano Zampini     extrowcum[mark] += size;
1184a13144ffSStefano Zampini   }
1185a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1186213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1187213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1188213b8bfaSStefano Zampini 
1189213b8bfaSStefano Zampini   /* Compress extrows */
1190a13144ffSStefano Zampini   cum  = 0;
1191a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1192a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1193a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1194a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1195a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1196a13144ffSStefano Zampini   }
1197a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1198a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1199a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1200a13144ffSStefano Zampini 
1201a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1202a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1203a13144ffSStefano Zampini 
1204a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1205a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1206c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1207c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1208a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1209a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1210a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12111e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1212a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1214213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1215a13144ffSStefano Zampini 
1216a13144ffSStefano Zampini   /* Defaults to identity */
1217c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1220a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1221a13144ffSStefano Zampini 
12221e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12231e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12241e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12251e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12261e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12271e0482f5SStefano Zampini     IS                     wis,gwis;
12281e0482f5SStefano Zampini     PetscInt               cnv,cne;
12291e0482f5SStefano Zampini 
12301e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12311e0482f5SStefano Zampini     if (fl2g) {
12321e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12331e0482f5SStefano Zampini     } else {
12341e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12351e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12361e0482f5SStefano Zampini     }
12371e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12381e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12391e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12401e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12411e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12421e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12431e0482f5SStefano Zampini 
12441e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12451e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12461e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12471e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12481e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12491e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12501e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12511e0482f5SStefano Zampini 
12521e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12531e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12541e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12551e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12561e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12571e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12581e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12591e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12601e0482f5SStefano Zampini   }
1261213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
12621e0482f5SStefano Zampini 
12631e0482f5SStefano Zampini #if defined(PRINT_GDET)
12641e0482f5SStefano Zampini   inc = 0;
12651e0482f5SStefano Zampini   lev = pcbddc->current_level;
12661e0482f5SStefano Zampini #endif
1267213b8bfaSStefano Zampini 
1268213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1269a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1270a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12711e0482f5SStefano Zampini     IS          cornersis = NULL;
12721e0482f5SStefano Zampini     PetscScalar cvals[2];
1273a13144ffSStefano Zampini 
12741e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12751e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12761e0482f5SStefano Zampini     }
12771e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1278a13144ffSStefano Zampini     if (Gins && GKins) {
1279a13144ffSStefano Zampini       PetscScalar    *data;
1280a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1281a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1282a13144ffSStefano Zampini 
1283a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1284a13144ffSStefano Zampini       /* H1 */
1285a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1286a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1287a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1288a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1289a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1290a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1291a13144ffSStefano Zampini       /* complement */
1292a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12936080607fSStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %D",i);
12946080607fSStefano 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);
12956080607fSStefano 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);
1296a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1297a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1298a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
12991e0482f5SStefano Zampini 
13001e0482f5SStefano Zampini       /* coarse discrete gradient */
13011e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13021e0482f5SStefano Zampini         PetscInt cols[2];
13031e0482f5SStefano Zampini 
13041e0482f5SStefano Zampini         cols[0] = 2*i;
13051e0482f5SStefano Zampini         cols[1] = 2*i+1;
13061e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13071e0482f5SStefano Zampini       }
1308a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1309a13144ffSStefano Zampini     }
1310a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1311a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13121e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1313a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1314a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1315a13144ffSStefano Zampini   }
1316213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1317a13144ffSStefano Zampini 
1318a13144ffSStefano Zampini   /* Start assembling */
1319a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13201e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13211e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13221e0482f5SStefano Zampini   }
1323a13144ffSStefano Zampini 
1324a13144ffSStefano Zampini   /* Free */
1325c2151214SStefano Zampini   if (fl2g) {
1326c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1327c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1328c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1329c2151214SStefano Zampini     }
1330c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1331c2151214SStefano Zampini   }
1332eee23b56SStefano Zampini 
1333eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1334eee23b56SStefano Zampini   {
1335eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1336eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1337eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1338eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1339eee23b56SStefano Zampini 
1340eee23b56SStefano Zampini     /* find first primal edge */
1341eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1342eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1343eee23b56SStefano Zampini     } else {
1344eee23b56SStefano Zampini       if (fl2g) {
1345eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1346eee23b56SStefano Zampini       }
1347eee23b56SStefano Zampini       idxs = cedges;
1348eee23b56SStefano Zampini     }
1349eee23b56SStefano Zampini     cum = 0;
1350eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1351eee23b56SStefano Zampini 
1352eee23b56SStefano Zampini     /* adapt connected components */
1353eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1354eee23b56SStefano Zampini     graph->cptr[0] = 0;
1355eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1356eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1357eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1358eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1359eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1360eee23b56SStefano Zampini         ncc++;
1361eee23b56SStefano Zampini         lc--;
1362eee23b56SStefano Zampini         cum++;
1363eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1364eee23b56SStefano Zampini       }
1365eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1366eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1367eee23b56SStefano Zampini       ncc++;
1368eee23b56SStefano Zampini     }
1369eee23b56SStefano Zampini     graph->ncc = ncc;
1370eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1371eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1372eee23b56SStefano Zampini     }
1373eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1374eee23b56SStefano Zampini   }
1375213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1376c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1377c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1378213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1379eee23b56SStefano Zampini 
1380c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1381a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1382a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1383b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1384b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1385a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1386a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1387a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1388a13144ffSStefano Zampini 
1389a13144ffSStefano Zampini   /* Complete assembling */
1390a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13911e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13921e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13931e0482f5SStefano Zampini #if 0
13941e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
13951e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
13961e0482f5SStefano Zampini #endif
13971e0482f5SStefano Zampini   }
1398a13144ffSStefano Zampini 
1399a13144ffSStefano Zampini   /* set change of basis */
1400213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1401a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1402a13144ffSStefano Zampini 
1403a13144ffSStefano Zampini   PetscFunctionReturn(0);
1404a13144ffSStefano Zampini }
1405a13144ffSStefano Zampini 
1406d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1407d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1408d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1409d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1410d8203eabSStefano Zampini {
1411d8203eabSStefano Zampini   PetscErrorCode ierr;
1412d8203eabSStefano Zampini   PetscInt       i;
1413d8203eabSStefano Zampini 
1414d8203eabSStefano Zampini   PetscFunctionBegin;
1415d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1416d8203eabSStefano Zampini     PetscInt first,last;
1417d8203eabSStefano Zampini 
1418d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
141986fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1420d8203eabSStefano Zampini     if (i>=first && i < last) {
1421d8203eabSStefano Zampini       PetscScalar *data;
1422d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1423d8203eabSStefano Zampini       if (!has_const) {
1424d8203eabSStefano Zampini         data[i-first] = 1.;
1425d8203eabSStefano Zampini       } else {
142686fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142786fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1428d8203eabSStefano Zampini       }
1429d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1430d8203eabSStefano Zampini     }
1431d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1432d8203eabSStefano Zampini   }
1433d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1434d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1435d8203eabSStefano Zampini     PetscInt first,last;
1436ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1437d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1438d8203eabSStefano Zampini     if (i>=first && i < last) {
1439d8203eabSStefano Zampini       PetscScalar *data;
1440d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1441d8203eabSStefano Zampini       if (!has_const) {
1442d8203eabSStefano Zampini         data[i-first] = 0.;
1443d8203eabSStefano Zampini       } else {
144486fa73c5SStefano Zampini         data[2*i-first] = 0.;
144586fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1446d8203eabSStefano Zampini       }
1447d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1448d8203eabSStefano Zampini     }
1449d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1450ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1451d8203eabSStefano Zampini   }
1452d8203eabSStefano Zampini   PetscFunctionReturn(0);
1453d8203eabSStefano Zampini }
1454d8203eabSStefano Zampini 
14558ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1456669cc0f4SStefano Zampini {
1457a198735bSStefano Zampini   Mat                    loc_divudotp;
1458fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14598ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1460669cc0f4SStefano Zampini   PetscScalar            *vals;
1461669cc0f4SStefano Zampini   const PetscScalar      *array;
1462a040e873SStefano Zampini   PetscInt               i,maxneighs,maxsize;
1463a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14641ae86dd6SStefano Zampini   PetscMPIInt            rank;
1465a198735bSStefano Zampini   PetscErrorCode         ierr;
1466669cc0f4SStefano Zampini 
1467669cc0f4SStefano Zampini   PetscFunctionBegin;
1468a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1469a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
14708037d520SStefano Zampini   if (!maxneighs) {
14718037d520SStefano Zampini     ierr  = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14728037d520SStefano Zampini     *nnsp = NULL;
14738037d520SStefano Zampini     PetscFunctionReturn(0);
1474669cc0f4SStefano Zampini   }
1475669cc0f4SStefano Zampini   maxsize = 0;
1476a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
1477669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1478669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1479669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14808ae0ca82SStefano Zampini   if (!transpose) {
14818ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14828ae0ca82SStefano Zampini   } else {
14838ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14848ae0ca82SStefano Zampini   }
1485669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14861ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1487d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1488669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1489ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
14908ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);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);
15129ad3d12aSKarl Rupp     ierr = VecScatterCreateWithData(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);
1533669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1534669cc0f4SStefano Zampini   }
1535a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1536fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1537fa23a32eSStefano Zampini   if (vl2l) {
1538187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1539fa23a32eSStefano Zampini   }
1540669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1541669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1542669cc0f4SStefano Zampini 
1543669cc0f4SStefano Zampini   /* assemble near null space */
1544669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1545669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1546669cc0f4SStefano Zampini   }
1547669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1548669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
15493272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
1550ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1551669cc0f4SStefano Zampini   }
1552669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1553669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1554669cc0f4SStefano Zampini }
1555669cc0f4SStefano Zampini 
15567620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15577620a527SStefano Zampini {
15587620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15597620a527SStefano Zampini   PetscErrorCode ierr;
15607620a527SStefano Zampini 
15617620a527SStefano Zampini   PetscFunctionBegin;
15627620a527SStefano Zampini   if (primalv) {
15637620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15647620a527SStefano Zampini       IS list[2], newp;
15657620a527SStefano Zampini 
15667620a527SStefano Zampini       list[0] = primalv;
15677620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15687620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
15697620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
15707620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
15717620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15727620a527SStefano Zampini     } else {
15737620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
15747620a527SStefano Zampini     }
15757620a527SStefano Zampini   }
15767620a527SStefano Zampini   PetscFunctionReturn(0);
15777620a527SStefano Zampini }
1578669cc0f4SStefano Zampini 
15791c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15801c7a958bSStefano Zampini {
15811c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15821c7a958bSStefano Zampini 
15831c7a958bSStefano Zampini   PetscFunctionBegin;
15841c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15851c7a958bSStefano Zampini   PetscFunctionReturn(0);
15861c7a958bSStefano Zampini }
1587674ae819SStefano Zampini 
15881f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15891f4df5f7SStefano Zampini {
15901f4df5f7SStefano Zampini   PetscErrorCode ierr;
15911f4df5f7SStefano Zampini   Vec            local,global;
15921f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15931f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15945c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15951f4df5f7SStefano Zampini 
15961f4df5f7SStefano Zampini   PetscFunctionBegin;
15975c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
15985c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
15995c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16001f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
160121ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16021f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16036a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16046a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16056a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16066a8fc67bSStefano Zampini     }
16076a8fc67bSStefano Zampini     goto boundary;
16086a8fc67bSStefano Zampini   }
16095c5e10d6SStefano Zampini 
16101f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16111f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16121f4df5f7SStefano Zampini       PetscInt i;
16130c85b387SStefano Zampini 
16141f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16151f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16160c85b387SStefano Zampini         PetscInt bs;
16170c85b387SStefano Zampini 
16181f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16190c85b387SStefano Zampini         ierr = ISGetBlockSize(pcbddc->ISForDofs[i],&bs);CHKERRQ(ierr);
16200c85b387SStefano Zampini         ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
16211f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16221f4df5f7SStefano Zampini       }
16231f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16241f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16251f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16261f4df5f7SStefano Zampini     }
16271f4df5f7SStefano Zampini   } else {
162821ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
162921ef3d20SStefano Zampini       DM dm;
163021ef3d20SStefano Zampini 
163121ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
163221ef3d20SStefano Zampini       if (!dm) {
163321ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
163421ef3d20SStefano Zampini       }
163521ef3d20SStefano Zampini       if (dm) {
163621ef3d20SStefano Zampini         IS      *fields;
163721ef3d20SStefano Zampini         PetscInt nf,i;
16380c85b387SStefano Zampini 
163921ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
164021ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
164121ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16420c85b387SStefano Zampini           PetscInt bs;
16430c85b387SStefano Zampini 
164421ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16450c85b387SStefano Zampini           ierr = ISGetBlockSize(fields[i],&bs);CHKERRQ(ierr);
16460c85b387SStefano Zampini           ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
164721ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
164821ef3d20SStefano Zampini         }
164921ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
165021ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
165121ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
165221ef3d20SStefano Zampini         PetscContainer   c;
165321ef3d20SStefano Zampini 
165421ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
165521ef3d20SStefano Zampini         if (c) {
165621ef3d20SStefano Zampini           MatISLocalFields lf;
165721ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
165821ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
165921ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16601f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1661986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
166221ef3d20SStefano Zampini           if (i > 1) {
1663986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16641f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16651f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16661f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16671f4df5f7SStefano Zampini             }
16681f4df5f7SStefano Zampini           }
166921ef3d20SStefano Zampini         }
167021ef3d20SStefano Zampini       }
16717a0e7b2cSstefano_zampini     } else {
16727a0e7b2cSstefano_zampini       PetscInt i;
16737a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16747a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16757a0e7b2cSstefano_zampini       }
16761f4df5f7SStefano Zampini     }
1677986cdee1SStefano Zampini   }
16781f4df5f7SStefano Zampini 
16795c5e10d6SStefano Zampini boundary:
16801f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16811f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16827a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16837a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16841f4df5f7SStefano Zampini   }
16851f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16861f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16877a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16887a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16891f4df5f7SStefano Zampini   }
16901f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16911f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16921f4df5f7SStefano Zampini   }
16931f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16941f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16957620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16967620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16977620a527SStefano Zampini     IS        primalv = NULL;
16987620a527SStefano Zampini     PetscInt  i;
16998361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
17007a0e7b2cSstefano_zampini 
17017620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17027620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17037620a527SStefano Zampini     }
17047620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17058361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17067620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17077620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17087620a527SStefano Zampini   }
17097620a527SStefano Zampini   /* early stage corner detection */
17107620a527SStefano Zampini   {
17117620a527SStefano Zampini     DM dm;
17127620a527SStefano Zampini 
17137620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17147620a527SStefano Zampini     if (dm) {
17157620a527SStefano Zampini       PetscBool isda;
17167620a527SStefano Zampini 
17177620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17187620a527SStefano Zampini       if (isda) {
17197620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17207620a527SStefano Zampini         IS                     corners;
17217620a527SStefano Zampini         Mat                    lA;
17227620a527SStefano Zampini 
1723d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17247620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17257620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17267620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
1727fa55603eSStefano Zampini         if (l2l && corners) {
17287620a527SStefano Zampini           const PetscInt *idx;
172972ed36d8SStefano Zampini           PetscInt       dof,bs,*idxout,n;
17307620a527SStefano Zampini 
173172ed36d8SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17327620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17337620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17347620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
173572ed36d8SStefano Zampini           if (bs == dof) {
17367620a527SStefano Zampini             ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17377620a527SStefano Zampini             ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
173872ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
173972ed36d8SStefano Zampini             PetscInt i,d;
174072ed36d8SStefano Zampini 
174172ed36d8SStefano Zampini             ierr = PetscMalloc1(dof*n,&idxout);CHKERRQ(ierr);
174272ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
174372ed36d8SStefano Zampini             ierr = ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout);CHKERRQ(ierr);
174472ed36d8SStefano Zampini 
174572ed36d8SStefano Zampini             bs = 1;
174672ed36d8SStefano Zampini             n *= dof;
174772ed36d8SStefano Zampini           }
17487620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1749d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17507620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17517620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17527620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17531c7a958bSStefano Zampini           pcbddc->corner_selected = PETSC_TRUE;
1754fa55603eSStefano Zampini         } else if (corners) { /* not from DMDA */
1755d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17567620a527SStefano Zampini         }
17577620a527SStefano Zampini       }
17587620a527SStefano Zampini     }
17597620a527SStefano Zampini   }
17601c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
17611c7a958bSStefano Zampini     DM dm;
17621c7a958bSStefano Zampini 
17631c7a958bSStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17641c7a958bSStefano Zampini     if (!dm) {
17651c7a958bSStefano Zampini       ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17661c7a958bSStefano Zampini     }
17671c7a958bSStefano Zampini     if (dm) {
17681c7a958bSStefano Zampini       Vec            vcoords;
17691c7a958bSStefano Zampini       PetscSection   section;
17701c7a958bSStefano Zampini       PetscReal      *coords;
17711c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
17721c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
17731c7a958bSStefano Zampini 
17741c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
1775e87a4003SBarry Smith       ierr = DMGetSection(dm,&section);CHKERRQ(ierr);
17761c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
17771c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
17781c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
17791c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
17801c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
17811c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
17821c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
17831c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
17841c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
17851c7a958bSStefano Zampini         PetscInt          i;
17861c7a958bSStefano Zampini         const PetscScalar *v;
17871c7a958bSStefano Zampini 
17881c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
17891c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
17901c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
17911c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
17921c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
17931c7a958bSStefano Zampini       }
17941c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
17951c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
17961c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
17971c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
17981c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
17991c7a958bSStefano Zampini     }
18001c7a958bSStefano Zampini   }
18017a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18027a0e7b2cSstefano_zampini }
18037a0e7b2cSstefano_zampini 
18047a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18057a0e7b2cSstefano_zampini {
18067a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18077a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
18087a0e7b2cSstefano_zampini   IS              nis;
18097a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18107a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18117a0e7b2cSstefano_zampini   PetscBool       *ld;
18127a0e7b2cSstefano_zampini 
18137a0e7b2cSstefano_zampini   PetscFunctionBegin;
18147a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18157a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18167a0e7b2cSstefano_zampini     /* init rootdata with true */
18177a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
18187a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
18197a0e7b2cSstefano_zampini   } else {
18207a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
18217a0e7b2cSstefano_zampini   }
18227a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18237a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18247a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18257a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18267a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18277a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18287a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18297a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18307a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18317a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18327a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18337a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18347a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18357a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18367a0e7b2cSstefano_zampini   } else {
18377a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18387a0e7b2cSstefano_zampini   }
18397a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18407a0e7b2cSstefano_zampini     if (ld[i])
18417a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18427a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18437a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18447a0e7b2cSstefano_zampini   *is  = nis;
18451f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18461f4df5f7SStefano Zampini }
18471f4df5f7SStefano Zampini 
18483e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18493e589ea0SStefano Zampini {
18503e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18513e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18523e589ea0SStefano Zampini   PetscErrorCode    ierr;
18533e589ea0SStefano Zampini 
18543e589ea0SStefano Zampini   PetscFunctionBegin;
18553e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18563e589ea0SStefano Zampini     PetscFunctionReturn(0);
18573e589ea0SStefano Zampini   }
18583e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18593e589ea0SStefano Zampini     Vec swap;
18603e589ea0SStefano Zampini 
18613e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18623e589ea0SStefano Zampini     swap = pcbddc->work_change;
18633e589ea0SStefano Zampini     pcbddc->work_change = r;
18643e589ea0SStefano Zampini     r = swap;
18653e589ea0SStefano Zampini   }
18663e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18673e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18683e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18693e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18703e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18713e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18723e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1873f913dca9SStefano Zampini     pcbddc->work_change = r;
18743e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18753e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18763e589ea0SStefano Zampini   }
18773e589ea0SStefano Zampini   PetscFunctionReturn(0);
18783e589ea0SStefano Zampini }
18793e589ea0SStefano Zampini 
1880a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1881a3df083aSStefano Zampini {
1882a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1883a3df083aSStefano Zampini   PetscErrorCode          ierr;
1884a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1885a3df083aSStefano Zampini 
1886a3df083aSStefano Zampini   PetscFunctionBegin;
1887a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1888a3df083aSStefano Zampini   if (transpose) {
1889a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1890a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1891a3df083aSStefano Zampini   } else {
1892a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1893a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1894a3df083aSStefano Zampini   }
1895a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1896a3df083aSStefano Zampini   if (apply_right) {
1897a3df083aSStefano Zampini     const PetscScalar *ax;
1898a3df083aSStefano Zampini     PetscInt          nl,i;
1899a3df083aSStefano Zampini 
1900a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1901a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1902a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1903a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1904a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1905a3df083aSStefano Zampini       PetscScalar    sum,val;
1906a3df083aSStefano Zampini       const PetscInt *idxs;
1907a3df083aSStefano Zampini       PetscInt       nz,j;
1908a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1909a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1910a3df083aSStefano Zampini       sum = 0.;
1911a3df083aSStefano Zampini       if (ctx->apply_p0) {
1912a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1913a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1914a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1915a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1916a3df083aSStefano Zampini         }
1917a3df083aSStefano Zampini       } else {
1918a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1919a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1920a3df083aSStefano Zampini         }
1921a3df083aSStefano Zampini       }
1922a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1923a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1924a3df083aSStefano Zampini     }
1925a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1926a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1927a3df083aSStefano Zampini   }
1928a3df083aSStefano Zampini   if (transpose) {
1929a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1930a3df083aSStefano Zampini   } else {
1931a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1932a3df083aSStefano Zampini   }
1933a3df083aSStefano Zampini   if (reset_x) {
1934a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1935a3df083aSStefano Zampini   }
1936a3df083aSStefano Zampini   if (apply_left) {
1937a3df083aSStefano Zampini     PetscScalar *ay;
1938a3df083aSStefano Zampini     PetscInt    i;
1939a3df083aSStefano Zampini 
1940a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1941a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1942a3df083aSStefano Zampini       PetscScalar    sum,val;
1943a3df083aSStefano Zampini       const PetscInt *idxs;
1944a3df083aSStefano Zampini       PetscInt       nz,j;
1945a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1946a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1947a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1948a3df083aSStefano Zampini       if (ctx->apply_p0) {
1949a3df083aSStefano Zampini         sum = 0.;
1950a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1951a3df083aSStefano Zampini           sum += ay[idxs[j]];
1952a3df083aSStefano Zampini           ay[idxs[j]] += val;
1953a3df083aSStefano Zampini         }
1954a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1955a3df083aSStefano Zampini       } else {
1956a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1957a3df083aSStefano Zampini           ay[idxs[j]] += val;
1958a3df083aSStefano Zampini         }
1959a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1960a3df083aSStefano Zampini       }
1961a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1962a3df083aSStefano Zampini     }
1963a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1964a3df083aSStefano Zampini   }
1965a3df083aSStefano Zampini   PetscFunctionReturn(0);
1966a3df083aSStefano Zampini }
1967a3df083aSStefano Zampini 
1968a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1969a3df083aSStefano Zampini {
1970a3df083aSStefano Zampini   PetscErrorCode ierr;
1971a3df083aSStefano Zampini 
1972a3df083aSStefano Zampini   PetscFunctionBegin;
1973a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1974a3df083aSStefano Zampini   PetscFunctionReturn(0);
1975a3df083aSStefano Zampini }
1976a3df083aSStefano Zampini 
1977a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1978a3df083aSStefano Zampini {
1979a3df083aSStefano Zampini   PetscErrorCode ierr;
1980a3df083aSStefano Zampini 
1981a3df083aSStefano Zampini   PetscFunctionBegin;
1982a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1983a3df083aSStefano Zampini   PetscFunctionReturn(0);
1984a3df083aSStefano Zampini }
1985a3df083aSStefano Zampini 
1986a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1987a3df083aSStefano Zampini {
1988a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1989a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1990a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1991a3df083aSStefano Zampini   PetscErrorCode          ierr;
1992a3df083aSStefano Zampini 
1993a3df083aSStefano Zampini   PetscFunctionBegin;
1994a3df083aSStefano Zampini   if (!restore) {
19951dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1996a3df083aSStefano Zampini     PetscScalar        *work;
1997b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1998a3df083aSStefano Zampini 
19999a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20009a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
2001a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
2002a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
2003a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2004a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
2005a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
2006a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
2007a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2008a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2009a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2010a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2011a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2012a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2013059032f7SStefano Zampini     if (reuse) {
2014a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20151dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2016059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2017059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2018059032f7SStefano Zampini       PetscInt               i;
2019059032f7SStefano Zampini 
2020059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2021059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2022059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2023059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2024059032f7SStefano Zampini       }
2025059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20261dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2027059032f7SStefano Zampini     }
2028a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2029a3df083aSStefano Zampini     ctx->work = work;
2030a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2031a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2032a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2033a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2034a3df083aSStefano Zampini 
2035a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2036a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2037a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2038a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2039a3df083aSStefano Zampini   } else {
20401dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20411dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20421dd7afcfSStefano Zampini     }
2043a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2044a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2045a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20461dd7afcfSStefano Zampini     ctx->A = NULL;
20471dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20481dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20491dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20501dd7afcfSStefano Zampini     if (ctx->free) {
2051059032f7SStefano Zampini       PetscInt i;
20521dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2053059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2054059032f7SStefano Zampini       }
2055059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2056059032f7SStefano Zampini     }
2057a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2058a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2059a3df083aSStefano Zampini   }
2060a3df083aSStefano Zampini   PetscFunctionReturn(0);
2061a3df083aSStefano Zampini }
2062a3df083aSStefano Zampini 
2063a3df083aSStefano Zampini /* used just in bddc debug mode */
2064a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2065a3df083aSStefano Zampini {
2066a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2067a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2068a3df083aSStefano Zampini   Mat            An;
2069a3df083aSStefano Zampini   PetscErrorCode ierr;
2070a3df083aSStefano Zampini 
2071a3df083aSStefano Zampini   PetscFunctionBegin;
2072a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2073a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2074a3df083aSStefano Zampini   if (is1) {
20757dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2076a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2077a3df083aSStefano Zampini   } else {
2078a3df083aSStefano Zampini     *B = An;
2079a3df083aSStefano Zampini   }
2080a3df083aSStefano Zampini   PetscFunctionReturn(0);
2081a3df083aSStefano Zampini }
2082a3df083aSStefano Zampini 
20831cf9b237SStefano Zampini /* TODO: add reuse flag */
20841cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20851cf9b237SStefano Zampini {
20861cf9b237SStefano Zampini   Mat            Bt;
20871cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20881cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20891cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20901cf9b237SStefano Zampini   PetscBool      flg_row;
20911cf9b237SStefano Zampini   PetscErrorCode ierr;
20921cf9b237SStefano Zampini 
20931cf9b237SStefano Zampini   PetscFunctionBegin;
20941cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20951cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20961cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20971cf9b237SStefano Zampini   nnz = n;
20981cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20991cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21001cf9b237SStefano Zampini   }
21011cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
21021cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
21031cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
21041cf9b237SStefano Zampini   nnz = 0;
21051cf9b237SStefano Zampini   bii[0] = 0;
21061cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21071cf9b237SStefano Zampini     PetscInt j;
21081cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21091cf9b237SStefano Zampini       PetscScalar entry = a[j];
21103272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21111cf9b237SStefano Zampini         bij[nnz] = ij[j];
21121cf9b237SStefano Zampini         bdata[nnz] = entry;
21131cf9b237SStefano Zampini         nnz++;
21141cf9b237SStefano Zampini       }
21151cf9b237SStefano Zampini     }
21161cf9b237SStefano Zampini     bii[i+1] = nnz;
21171cf9b237SStefano Zampini   }
21181cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21191cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21201cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21211cf9b237SStefano Zampini   {
21221cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21231cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21241cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21251cf9b237SStefano Zampini   }
21263272d46bSStefano Zampini   if (*B == A) {
21273272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21283272d46bSStefano Zampini   }
21291cf9b237SStefano Zampini   *B = Bt;
21301cf9b237SStefano Zampini   PetscFunctionReturn(0);
21311cf9b237SStefano Zampini }
21321cf9b237SStefano Zampini 
21338361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21344f1b2e48SStefano Zampini {
2135c80a6c00SStefano Zampini   Mat                    B = NULL;
2136c80a6c00SStefano Zampini   DM                     dm;
21374f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21384f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21394f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2140c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21414f1b2e48SStefano Zampini   PetscInt               i,n;
21424f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2143c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21444f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21454f1b2e48SStefano Zampini 
21464f1b2e48SStefano Zampini   PetscFunctionBegin;
2147a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2148a2eca866SStefano Zampini   if (cc) *cc = NULL;
2149a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2150c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2151c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2152c80a6c00SStefano Zampini   if (!dm) {
2153c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2154c80a6c00SStefano Zampini   }
2155c80a6c00SStefano Zampini   if (dm) {
2156c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2157c80a6c00SStefano Zampini   }
21588361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
21598361f951SStefano Zampini 
2160c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2161c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2162c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2163c80a6c00SStefano Zampini     IS             cellNumbering;
2164c80a6c00SStefano Zampini     const PetscInt *cellNum;
2165c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2166c80a6c00SStefano Zampini     PetscSection   section;
2167c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2168c80a6c00SStefano Zampini     PetscSF        sfPoint;
2169c80a6c00SStefano Zampini     PetscErrorCode ierr;
2170c80a6c00SStefano Zampini 
2171c80a6c00SStefano Zampini     PetscFunctionBegin;
2172c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2173c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2174c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2175c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2176c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2177c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2178c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2179c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2180c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2181c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2182c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2183c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2184956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2185c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2186c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2187c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2188c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2189c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2190c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2191c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2192c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21935cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2194c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2195c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2196c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2197c80a6c00SStefano Zampini           *pBuf = point;
2198c80a6c00SStefano Zampini         }
2199c80a6c00SStefano Zampini       }
2200c80a6c00SStefano Zampini       n++;
2201c80a6c00SStefano Zampini     }
2202c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2203c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2204c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2205c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2206c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2207c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2208c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2209c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2210c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2211c80a6c00SStefano Zampini     }
2212c80a6c00SStefano Zampini     xadj[n] = size;
2213c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2214c80a6c00SStefano Zampini     /* Clean up */
2215c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2216c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2217c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2218c80a6c00SStefano Zampini     graph->xadj = xadj;
2219c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2220c80a6c00SStefano Zampini   } else {
2221c80a6c00SStefano Zampini     Mat       A;
22228361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2223c80a6c00SStefano Zampini 
2224c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
222563c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2226a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
222763c961adSStefano Zampini       PetscFunctionReturn(0);
222863c961adSStefano Zampini     }
22294f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22304f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22311cf9b237SStefano Zampini       PetscBool isseqdense;
22321cf9b237SStefano Zampini 
22331cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22341cf9b237SStefano Zampini       if (!isseqdense) {
22354f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22361cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22371cf9b237SStefano Zampini         PetscScalar *array;
22381cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22391cf9b237SStefano Zampini 
22401cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22411cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22421cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22431cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22441cf9b237SStefano Zampini           PetscInt j;
22451cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22461cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22471cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22481cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22491cf9b237SStefano Zampini           }
22501cf9b237SStefano Zampini         }
22511cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22529d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22531cf9b237SStefano Zampini       }
22544f1b2e48SStefano Zampini     } else {
2255c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22564f1b2e48SStefano Zampini       B = A;
22574f1b2e48SStefano Zampini     }
22584f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22594f1b2e48SStefano Zampini 
22604f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22614f1b2e48SStefano Zampini     if (filter) {
22624f1b2e48SStefano Zampini       PetscScalar *data;
22634f1b2e48SStefano Zampini       PetscInt    j,cum;
22644f1b2e48SStefano Zampini 
22654f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22664f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22674f1b2e48SStefano Zampini       cum = 0;
22684f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22694f1b2e48SStefano Zampini         PetscInt t;
22704f1b2e48SStefano Zampini 
22714f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22724f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22734f1b2e48SStefano Zampini             continue;
22744f1b2e48SStefano Zampini           }
22754f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22764f1b2e48SStefano Zampini         }
22774f1b2e48SStefano Zampini         t = xadj_filtered[i];
22784f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22794f1b2e48SStefano Zampini         cum += t;
22804f1b2e48SStefano Zampini       }
22814f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22824f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22834f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22844f1b2e48SStefano Zampini     } else {
22854f1b2e48SStefano Zampini       graph->xadj = xadj;
22864f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22874f1b2e48SStefano Zampini     }
2288c80a6c00SStefano Zampini   }
2289c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2290c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2291c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2292c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2293c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2294c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22954f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22964f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2297c80a6c00SStefano Zampini 
22984f1b2e48SStefano Zampini   /* partial clean up */
22994f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2300c80a6c00SStefano Zampini   if (B) {
2301c80a6c00SStefano Zampini     PetscBool flg_row;
23024f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23034f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
23044f1b2e48SStefano Zampini   }
2305c80a6c00SStefano Zampini   if (isplex) {
2306c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2307c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2308c80a6c00SStefano Zampini   }
23094f1b2e48SStefano Zampini 
23104f1b2e48SStefano Zampini   /* get back data */
2311c80a6c00SStefano Zampini   if (isplex) {
2312c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2313c80a6c00SStefano Zampini     if (cc || primalv) {
2314c80a6c00SStefano Zampini       Mat          A;
2315c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2316c80a6c00SStefano Zampini       PetscSection subSection;
2317c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2318c80a6c00SStefano Zampini 
2319c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2320c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2321c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2322c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2323c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2324c80a6c00SStefano Zampini 
2325c80a6c00SStefano Zampini       cids[0] = 0;
2326c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2327c80a6c00SStefano Zampini         PetscInt j;
2328c80a6c00SStefano Zampini 
2329c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2330c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2331c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2332c80a6c00SStefano Zampini 
2333c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2334c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2335c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2336c80a6c00SStefano Zampini 
2337c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2338c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2339c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2340c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2341c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2342c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2343c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2344c80a6c00SStefano Zampini               } else { /* cross-vertex */
2345c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2346c80a6c00SStefano Zampini               }
2347c80a6c00SStefano Zampini             }
2348c80a6c00SStefano Zampini           }
2349c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2350c80a6c00SStefano Zampini         }
2351c80a6c00SStefano Zampini         cids[i+1] = cum;
2352c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2353c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2354c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2355c80a6c00SStefano Zampini         }
2356c80a6c00SStefano Zampini       }
2357c80a6c00SStefano Zampini       if (cc) {
2358c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2359c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2360c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2361c80a6c00SStefano Zampini         }
2362c80a6c00SStefano Zampini         *cc = cc_n;
2363c80a6c00SStefano Zampini       }
2364c80a6c00SStefano Zampini       if (primalv) {
2365c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2366c80a6c00SStefano Zampini       }
2367c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2368c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2369c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2370c80a6c00SStefano Zampini     }
2371c80a6c00SStefano Zampini   } else {
23721cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23731cf9b237SStefano Zampini     if (cc) {
23744f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23754f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23764f1b2e48SStefano 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);
23774f1b2e48SStefano Zampini       }
23784f1b2e48SStefano Zampini       *cc = cc_n;
23791cf9b237SStefano Zampini     }
2380c80a6c00SStefano Zampini   }
23814f1b2e48SStefano Zampini   /* clean up graph */
23824f1b2e48SStefano Zampini   graph->xadj = 0;
23834f1b2e48SStefano Zampini   graph->adjncy = 0;
23844f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23854f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23864f1b2e48SStefano Zampini }
23874f1b2e48SStefano Zampini 
23885408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23895408967cSStefano Zampini {
23905408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23915408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2392dee84bffSStefano Zampini   IS             dirIS = NULL;
23934f1b2e48SStefano Zampini   PetscInt       i;
23945408967cSStefano Zampini   PetscErrorCode ierr;
23955408967cSStefano Zampini 
23965408967cSStefano Zampini   PetscFunctionBegin;
2397dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
23985408967cSStefano Zampini   if (zerodiag) {
23995408967cSStefano Zampini     Mat            A;
24005408967cSStefano Zampini     Vec            vec3_N;
24015408967cSStefano Zampini     PetscScalar    *vals;
24025408967cSStefano Zampini     const PetscInt *idxs;
2403d12d3064SStefano Zampini     PetscInt       nz,*count;
24045408967cSStefano Zampini 
24055408967cSStefano Zampini     /* p0 */
24065408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
24075408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24085408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24095408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24104f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24115408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24125408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24135408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24145408967cSStefano Zampini     /* v_I */
24155408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24165408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24175408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24185408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24195408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24205408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24215408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24225408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24235408967cSStefano Zampini     if (dirIS) {
24245408967cSStefano Zampini       PetscInt n;
24255408967cSStefano Zampini 
24265408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24275408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24285408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24295408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24305408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24315408967cSStefano Zampini     }
24325408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24335408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24345408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24355408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2436669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24375408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24385408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24399a962809SStefano 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]));
24405408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24415408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2442d12d3064SStefano Zampini 
2443d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2444d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2445d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2446d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2447d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2448d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24496080607fSStefano 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]);
2450d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2451d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24525408967cSStefano Zampini   }
2453dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24545408967cSStefano Zampini 
24555408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24565408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24574f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24585408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24594f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24605408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2461f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2462f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
24636080607fSStefano 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);
2464f2a566d8SStefano Zampini   }
24655408967cSStefano Zampini   PetscFunctionReturn(0);
24665408967cSStefano Zampini }
24675408967cSStefano Zampini 
24683b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2469339f8db1SStefano Zampini {
2470339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24713b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
24723b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
24734edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24744edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2475339f8db1SStefano Zampini   PetscErrorCode ierr;
2476339f8db1SStefano Zampini 
2477339f8db1SStefano Zampini   PetscFunctionBegin;
24783b03f7bbSStefano Zampini   if (reuse) goto project_b0;
24799f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24809f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2481a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2482a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2483a3df083aSStefano Zampini   }
2484a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
24853b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
24863b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
24873b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
24883b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
24894f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24904f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24911ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24924f1b2e48SStefano Zampini   */
249340fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24947fbe2174Sstefano_zampini     IS        iP = NULL;
24953b03f7bbSStefano Zampini     PetscInt  p,*pp;
24963b03f7bbSStefano Zampini     PetscBool flg;
24974f1b2e48SStefano Zampini 
24983b03f7bbSStefano Zampini     ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp);CHKERRQ(ierr);
24993b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
250028b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
25013b03f7bbSStefano Zampini     ierr = PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg);CHKERRQ(ierr);
250228b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
25033b03f7bbSStefano Zampini     if (!flg) {
25043b03f7bbSStefano Zampini       n = 1;
25053b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25063b03f7bbSStefano Zampini     }
25073b03f7bbSStefano Zampini 
25083b03f7bbSStefano Zampini     bsp = 0;
25093b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25103b03f7bbSStefano Zampini       PetscInt bs;
25113b03f7bbSStefano Zampini 
25123b03f7bbSStefano 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]);
25133b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25143b03f7bbSStefano Zampini       bsp += bs;
25153b03f7bbSStefano Zampini     }
25163b03f7bbSStefano Zampini     ierr = PetscMalloc1(bsp,&bzerodiag);CHKERRQ(ierr);
25173b03f7bbSStefano Zampini     bsp  = 0;
25183b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25193b03f7bbSStefano Zampini       const PetscInt *idxs;
25203b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25213b03f7bbSStefano Zampini 
25223b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25233b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl);CHKERRQ(ierr);
25243b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25253b03f7bbSStefano Zampini       ierr = PetscMalloc1(npl/bs,&bidxs);CHKERRQ(ierr);
25263b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25273b03f7bbSStefano Zampini         PetscInt i;
25283b03f7bbSStefano Zampini 
25293b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25303b03f7bbSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]);CHKERRQ(ierr);
25313b03f7bbSStefano Zampini         bsp++;
25323b03f7bbSStefano Zampini       }
25333b03f7bbSStefano Zampini       ierr = PetscFree(bidxs);CHKERRQ(ierr);
25343b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25353b03f7bbSStefano Zampini     }
25363b03f7bbSStefano Zampini     ierr = ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures);CHKERRQ(ierr);
25373b03f7bbSStefano Zampini 
25387fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25397fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
25407fbe2174Sstefano_zampini     if (iP) {
25417fbe2174Sstefano_zampini       IS newpressures;
25427fbe2174Sstefano_zampini 
25437fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
25447fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
25457fbe2174Sstefano_zampini       pressures = newpressures;
25467fbe2174Sstefano_zampini     }
254740fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
254840fa8d13SStefano Zampini     if (!sorted) {
254940fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
255040fa8d13SStefano Zampini     }
25513b03f7bbSStefano Zampini     ierr = PetscFree(pp);CHKERRQ(ierr);
255240fa8d13SStefano Zampini   }
25533b03f7bbSStefano Zampini 
255497d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
255597d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
255627b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
255797d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2558339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2559339f8db1SStefano Zampini   if (!sorted) {
2560339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2561339f8db1SStefano Zampini   }
25624edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25634edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2564339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25654f1b2e48SStefano Zampini   if (!nz) {
25664f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25674f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
256840fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
256940fa8d13SStefano Zampini   }
25704f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25713b03f7bbSStefano Zampini 
25724f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25734f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25743b03f7bbSStefano Zampini   benign_n         = 0;
25751f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25761f4df5f7SStefano Zampini   interior_dofs    = NULL;
25774edc6404Sstefano_zampini   nneu             = 0;
25784edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25794edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25804edc6404Sstefano_zampini   }
25813369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25824edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25831f4df5f7SStefano Zampini     PetscInt n,i,j;
25841f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25851f4df5f7SStefano Zampini     PetscInt *iwork;
25861f4df5f7SStefano Zampini 
25871f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25881f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25891f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25901f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
259190648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25921f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25931f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25941f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25951f4df5f7SStefano Zampini       if (!iwork[i])
25961f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25971f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25981f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25991f4df5f7SStefano Zampini   }
26004f1b2e48SStefano Zampini   if (has_null_pressures) {
26014f1b2e48SStefano Zampini     IS             *subs;
26024edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26031f4df5f7SStefano Zampini     const PetscInt *idxs;
26041f4df5f7SStefano Zampini     PetscScalar    *array;
26051f4df5f7SStefano Zampini     Vec            *work;
26061f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
26074f1b2e48SStefano Zampini 
26084f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26094f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26101f4df5f7SStefano 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) */
26114edc6404Sstefano_zampini     if (checkb) {
26121f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
26131f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
26141f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
26151f4df5f7SStefano Zampini       /* work[0] = 1_p */
26161f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
26171f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
26181f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26191f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
26201f4df5f7SStefano Zampini       /* work[0] = 1_v */
26211f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
26221f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
26231f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26241f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
26251f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
26261f4df5f7SStefano Zampini     }
26273b03f7bbSStefano Zampini 
26283b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26293b03f7bbSStefano Zampini       IS       *is;
26303b03f7bbSStefano Zampini       PetscInt b,totb;
26313b03f7bbSStefano Zampini 
26323b03f7bbSStefano Zampini       totb  = bsp;
26333b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26343b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
26353b03f7bbSStefano Zampini       ierr  = PetscCalloc1(nsubs*totb,&zerodiag_subs);CHKERRQ(ierr);
26363b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
26374f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
26384f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
26394f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
26404f1b2e48SStefano Zampini           PetscInt               nl;
26414f1b2e48SStefano Zampini 
26423b03f7bbSStefano Zampini           if (subs) {
26434f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
26443b03f7bbSStefano Zampini           } else {
26453b03f7bbSStefano Zampini             IS tis;
26463b03f7bbSStefano Zampini 
26473b03f7bbSStefano Zampini             ierr = MatGetLocalSize(pcbddc->local_mat,&nl,NULL);CHKERRQ(ierr);
26483b03f7bbSStefano Zampini             ierr = ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis);CHKERRQ(ierr);
26493b03f7bbSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(tis,&l2g);CHKERRQ(ierr);
26503b03f7bbSStefano Zampini             ierr = ISDestroy(&tis);CHKERRQ(ierr);
26513b03f7bbSStefano Zampini           }
26523b03f7bbSStefano Zampini           ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs);CHKERRQ(ierr);
26534f1b2e48SStefano Zampini           ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
26544f1b2e48SStefano Zampini           if (nl) {
26554f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
26564f1b2e48SStefano Zampini 
26574edc6404Sstefano_zampini             if (checkb) {
26581f4df5f7SStefano Zampini               ierr = VecSet(matis->x,0);CHKERRQ(ierr);
26591f4df5f7SStefano Zampini               ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
26601f4df5f7SStefano Zampini               ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
26611f4df5f7SStefano Zampini               ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26621f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26631f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26641f4df5f7SStefano Zampini               ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
26651f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
26661f4df5f7SStefano Zampini               ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
26671f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
26681f4df5f7SStefano Zampini               ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
26691f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
26701f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26711f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
26721f4df5f7SStefano Zampini                   break;
26731f4df5f7SStefano Zampini                 }
26741f4df5f7SStefano Zampini               }
26751f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26761f4df5f7SStefano Zampini             }
26776632bad2Sstefano_zampini             if (valid && nneu) {
26786632bad2Sstefano_zampini               const PetscInt *idxs;
26791f4df5f7SStefano Zampini               PetscInt       nzb;
26801f4df5f7SStefano Zampini 
26816632bad2Sstefano_zampini               ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26826632bad2Sstefano_zampini               ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26836632bad2Sstefano_zampini               ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26841f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
26851f4df5f7SStefano Zampini             }
26861f4df5f7SStefano Zampini             if (valid && pressures) {
26873b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
26883b03f7bbSStefano Zampini               PetscInt i1,i2;
26893b03f7bbSStefano Zampini 
26904f1b2e48SStefano Zampini               ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26913b03f7bbSStefano Zampini               ierr = ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp);CHKERRQ(ierr);
26923b03f7bbSStefano Zampini               ierr = ISGetLocalSize(tmp,&i1);CHKERRQ(ierr);
26933b03f7bbSStefano Zampini               ierr = ISGetLocalSize(t_zerodiag_subs,&i2);CHKERRQ(ierr);
26943b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
26954f1b2e48SStefano Zampini               ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26963b03f7bbSStefano Zampini               ierr = ISDestroy(&tmp);CHKERRQ(ierr);
26974f1b2e48SStefano Zampini             }
26984f1b2e48SStefano Zampini             if (valid) {
26993b03f7bbSStefano Zampini               ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]);CHKERRQ(ierr);
27003b03f7bbSStefano Zampini               benign_n++;
27013b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27024f1b2e48SStefano Zampini           }
27034f1b2e48SStefano Zampini           ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini           ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
27054f1b2e48SStefano Zampini         }
27063b03f7bbSStefano Zampini       }
27074f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27084f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27091f4df5f7SStefano Zampini 
27106632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27111f4df5f7SStefano Zampini       if (valid && pressures) {
27124f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
27134f1b2e48SStefano Zampini       }
27144edc6404Sstefano_zampini       if (valid && checkb) {
27151f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
27161f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
27171f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27181f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27191f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27201f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27211f4df5f7SStefano Zampini             break;
27221f4df5f7SStefano Zampini           }
27231f4df5f7SStefano Zampini         }
27241f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27251f4df5f7SStefano Zampini       }
27264f1b2e48SStefano Zampini       if (valid) {
27273b03f7bbSStefano Zampini         benign_n = 1;
27283b03f7bbSStefano Zampini         ierr = PetscMalloc1(benign_n,&zerodiag_subs);CHKERRQ(ierr);
27294f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
27304f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27314f1b2e48SStefano Zampini       }
27324f1b2e48SStefano Zampini     }
27334edc6404Sstefano_zampini     if (checkb) {
27341f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
27354f1b2e48SStefano Zampini     }
27361f4df5f7SStefano Zampini   }
27371f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
27384f1b2e48SStefano Zampini 
27393b03f7bbSStefano Zampini   if (!benign_n) {
2740b9b0e38cSStefano Zampini     PetscInt n;
2741b9b0e38cSStefano Zampini 
27424f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
27434f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2744b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2745b9b0e38cSStefano Zampini     if (n) {
27464f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
27474f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
27484f1b2e48SStefano Zampini     }
2749b9b0e38cSStefano Zampini   }
27504f1b2e48SStefano Zampini 
27514f1b2e48SStefano Zampini   /* final check for null pressures */
27524f1b2e48SStefano Zampini   if (zerodiag && pressures) {
27533b03f7bbSStefano Zampini     ierr = ISEqual(pressures,zerodiag,&have_null);CHKERRQ(ierr);
27544f1b2e48SStefano Zampini   }
27554f1b2e48SStefano Zampini 
27564f1b2e48SStefano Zampini   if (recompute_zerodiag) {
27574f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
27583b03f7bbSStefano Zampini     if (benign_n == 1) {
27594f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
27604f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
27614f1b2e48SStefano Zampini     } else {
27624f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
27634f1b2e48SStefano Zampini 
27644f1b2e48SStefano Zampini       nzn = 0;
27653b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
27664f1b2e48SStefano Zampini         PetscInt ns;
27674f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27684f1b2e48SStefano Zampini         nzn += ns;
27694f1b2e48SStefano Zampini       }
27704f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
27714f1b2e48SStefano Zampini       nzn = 0;
27723b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
27734f1b2e48SStefano Zampini         PetscInt ns,*idxs;
27744f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27754f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27764f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
27774f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27784f1b2e48SStefano Zampini         nzn += ns;
27794f1b2e48SStefano Zampini       }
27804f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27814f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27824f1b2e48SStefano Zampini     }
27834f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27844f1b2e48SStefano Zampini   }
27854f1b2e48SStefano Zampini 
27863b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
27873b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
27883b03f7bbSStefano Zampini 
2789669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2790a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2791a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2792a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2793a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2794a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2795a198735bSStefano Zampini 
27961f4df5f7SStefano Zampini     if (pressures) {
27971f4df5f7SStefano Zampini       isused = pressures;
27981f4df5f7SStefano Zampini     } else {
27994edc6404Sstefano_zampini       isused = zerodiag_save;
28001f4df5f7SStefano Zampini     }
2801a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2802669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
28031ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
28041ae86dd6SStefano 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");
2805a198735bSStefano Zampini     n_isused = 0;
2806a198735bSStefano Zampini     if (isused) {
2807a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2808a198735bSStefano Zampini     }
2809a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2810a198735bSStefano Zampini     st = st-n_isused;
28111ae86dd6SStefano Zampini     if (n) {
2812a198735bSStefano Zampini       const PetscInt *gidxs;
2813a198735bSStefano Zampini 
28147dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2815a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2816a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2817a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2818a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2819a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
28201ae86dd6SStefano Zampini     } else {
2821a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2822a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2823a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2824a198735bSStefano Zampini     }
2825a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2826a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2827a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2828a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2829a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2830a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2831a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2832a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2833a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2834a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2835a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2836a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2837a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2838a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
28391ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28401ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28411ae86dd6SStefano Zampini   }
28424edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
28433b03f7bbSStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
28443b03f7bbSStefano Zampini   if (bzerodiag) {
28453b03f7bbSStefano Zampini     PetscInt i;
2846b3afcdbeSStefano Zampini 
28473b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
28483b03f7bbSStefano Zampini       ierr = ISDestroy(&bzerodiag[i]);CHKERRQ(ierr);
28493b03f7bbSStefano Zampini     }
28503b03f7bbSStefano Zampini     ierr = PetscFree(bzerodiag);CHKERRQ(ierr);
28513b03f7bbSStefano Zampini   }
28523b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
28533b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28543b03f7bbSStefano Zampini 
28553b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
28563b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
28573b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
28583b03f7bbSStefano Zampini 
28593b03f7bbSStefano Zampini project_b0:
2860aa0d93e9SStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2861b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
28623b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
28634f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
28644f1b2e48SStefano Zampini 
2865339f8db1SStefano Zampini     /* local change of basis for pressures */
2866339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
286797d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2868339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2869339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2870339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
2871aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
28724f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2873aa0d93e9SStefano Zampini       const PetscInt *idxs;
28744f1b2e48SStefano Zampini       PetscInt       nzs,j;
28754f1b2e48SStefano Zampini 
28763b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs);CHKERRQ(ierr);
28773b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28784f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
28794f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
28803b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28814f1b2e48SStefano Zampini     }
2882339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2883e1b21442SStefano Zampini     ierr = MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2884339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2885aa0d93e9SStefano Zampini     /* set identity by default */
2886aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
2887aa0d93e9SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES);CHKERRQ(ierr);
2888339f8db1SStefano Zampini     }
28899f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
28904f1b2e48SStefano 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);
2891339f8db1SStefano Zampini     /* set change on pressures */
28924f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28934f1b2e48SStefano Zampini       PetscScalar    *array;
2894aa0d93e9SStefano Zampini       const PetscInt *idxs;
28954f1b2e48SStefano Zampini       PetscInt       nzs;
28964f1b2e48SStefano Zampini 
28973b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28983b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28994f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2900339f8db1SStefano Zampini         PetscScalar vals[2];
2901339f8db1SStefano Zampini         PetscInt    cols[2];
2902339f8db1SStefano Zampini 
2903339f8db1SStefano Zampini         cols[0] = idxs[i];
29044f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2905339f8db1SStefano Zampini         vals[0] = 1.;
2906b0f5fe93SStefano Zampini         vals[1] = 1.;
29074f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2908339f8db1SStefano Zampini       }
29094f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
29104f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29114f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29124f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
29134f1b2e48SStefano Zampini       /* store local idxs for p0 */
29144f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29153b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2916339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
29174f1b2e48SStefano Zampini     }
2918339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2919339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29203b03f7bbSStefano Zampini 
2921a3df083aSStefano Zampini     /* project if needed */
2922a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29231dd7afcfSStefano Zampini       Mat M;
29241dd7afcfSStefano Zampini 
29251dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2926339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
29271dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
29281dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2929a3df083aSStefano Zampini     }
29304f1b2e48SStefano Zampini     /* store global idxs for p0 */
29314f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2932339f8db1SStefano Zampini   }
2933339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2934339f8db1SStefano Zampini   PetscFunctionReturn(0);
2935339f8db1SStefano Zampini }
2936339f8db1SStefano Zampini 
2937015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2938efc2fbd9SStefano Zampini {
2939efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2940de9d7bd0SStefano Zampini   PetscScalar    *array;
2941efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2942efc2fbd9SStefano Zampini 
2943efc2fbd9SStefano Zampini   PetscFunctionBegin;
2944efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2945efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
29464f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2947efc2fbd9SStefano Zampini   }
2948de9d7bd0SStefano Zampini   if (get) {
2949efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
29504f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
29514f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2952efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2953de9d7bd0SStefano Zampini   } else {
2954de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2955de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2956de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2957de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2958efc2fbd9SStefano Zampini   }
2959efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2960efc2fbd9SStefano Zampini }
2961efc2fbd9SStefano Zampini 
2962c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2963c263805aSStefano Zampini {
2964c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2965c263805aSStefano Zampini   PetscErrorCode ierr;
2966c263805aSStefano Zampini 
2967c263805aSStefano Zampini   PetscFunctionBegin;
2968c263805aSStefano Zampini   /* TODO: add error checking
2969c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2970c263805aSStefano Zampini     - cannot push before pop.
29711c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2972c263805aSStefano Zampini   */
29734f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2974efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2975efc2fbd9SStefano Zampini   }
2976c263805aSStefano Zampini   if (pop) {
2977a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29784f1b2e48SStefano Zampini       IS       is_p0;
29794f1b2e48SStefano Zampini       MatReuse reuse;
2980c263805aSStefano Zampini 
2981c263805aSStefano Zampini       /* extract B_0 */
29824f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
29834f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
29844f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
29854f1b2e48SStefano Zampini       }
29864f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
29877dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2988c263805aSStefano Zampini       /* remove rows and cols from local problem */
2989c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
299097d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29914f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29924f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2993a3df083aSStefano Zampini     } else {
2994a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2995a3df083aSStefano Zampini       PetscScalar *vals;
2996a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2997a3df083aSStefano Zampini 
2998a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2999a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
3000a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30010b5adadeSStefano Zampini         PetscInt *nnz;
3002a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
3003a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
3004a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3005331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
3006331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
3007331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
3008331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3009331e053bSStefano Zampini         }
3010331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
3011e1b21442SStefano Zampini         ierr = MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3012331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
3013331e053bSStefano Zampini       }
3014a3df083aSStefano Zampini 
3015a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3016a3df083aSStefano Zampini         PetscScalar *array;
3017a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3018a3df083aSStefano Zampini 
3019a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
3020a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3021a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3022a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
3023a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
3024a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
3025a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
3026a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
3027a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
3028a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
3029a3df083aSStefano Zampini         cum = 0;
3030a3df083aSStefano Zampini         for (j=0;j<n;j++) {
303122db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3032a3df083aSStefano Zampini             vals[cum] = array[j];
3033a3df083aSStefano Zampini             idxs_ins[cum] = j;
3034a3df083aSStefano Zampini             cum++;
3035a3df083aSStefano Zampini           }
3036a3df083aSStefano Zampini         }
3037a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
3038a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
3039a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3040a3df083aSStefano Zampini       }
3041a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3042a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3043a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
3044a3df083aSStefano Zampini     }
3045c263805aSStefano Zampini   } else { /* push */
3046a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30474f1b2e48SStefano Zampini       PetscInt i;
30484f1b2e48SStefano Zampini 
30494f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
30504f1b2e48SStefano Zampini         PetscScalar *B0_vals;
30514f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
30524f1b2e48SStefano Zampini 
30534f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
30544f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
30557b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
30564f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
30574f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
30584f1b2e48SStefano Zampini       }
3059c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3060c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30616080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3062c263805aSStefano Zampini   }
3063c263805aSStefano Zampini   PetscFunctionReturn(0);
3064c263805aSStefano Zampini }
3065c263805aSStefano Zampini 
306608122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3067b1b3d7a2SStefano Zampini {
3068b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
306908122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
307008122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
307108122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
307208122e43SStefano Zampini   PetscScalar     *work,lwork;
307308122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
307408122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3075bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
30761b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3077f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
307808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
307908122e43SStefano Zampini   PetscReal       *rwork;
308008122e43SStefano Zampini #endif
3081b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3082b1b3d7a2SStefano Zampini 
3083b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3084b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3085af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3086bd2a564bSStefano 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);
308743371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
308806a4e24aSStefano Zampini 
3089fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3090fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3091fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3092fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30931575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3094fd14bc51SStefano Zampini   }
3095fd14bc51SStefano Zampini 
3096e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
30976080607fSStefano 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);
3098e496cd5dSStefano Zampini   }
3099e496cd5dSStefano Zampini 
310008122e43SStefano Zampini   /* max size of subsets */
310108122e43SStefano Zampini   mss = 0;
310208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
310308122e43SStefano Zampini     PetscInt subset_size;
3104862806e4SStefano Zampini 
310508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
310608122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
310708122e43SStefano Zampini   }
310808122e43SStefano Zampini 
310908122e43SStefano Zampini   /* min/max and threshold */
311008122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3111f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
311208122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3113f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3114bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3115f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3116f6f667cfSStefano Zampini   }
311708122e43SStefano Zampini 
311808122e43SStefano Zampini   /* allocate lapack workspace */
311908122e43SStefano Zampini   cum = cum2 = 0;
312008122e43SStefano Zampini   maxneigs = 0;
312108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
312208122e43SStefano Zampini     PetscInt n,subset_size;
3123f6f667cfSStefano Zampini 
312408122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
312508122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31269162d606SStefano Zampini     cum += subset_size;
31279162d606SStefano Zampini     cum2 += subset_size*n;
312808122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
312908122e43SStefano Zampini   }
313008122e43SStefano Zampini   if (mss) {
3131bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
313208122e43SStefano Zampini       PetscBLASInt B_itype = 1;
313308122e43SStefano Zampini       PetscBLASInt B_N = mss;
31344c6709b3SStefano Zampini       PetscReal    zero = 0.0;
31354c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
313608122e43SStefano Zampini 
313708122e43SStefano Zampini       B_lwork = -1;
313808122e43SStefano Zampini       S = NULL;
313908122e43SStefano Zampini       St = NULL;
3140a58a30b4SStefano Zampini       eigs = NULL;
3141a58a30b4SStefano Zampini       eigv = NULL;
3142a58a30b4SStefano Zampini       B_iwork = NULL;
3143a58a30b4SStefano Zampini       B_ifail = NULL;
3144d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3145d1710679SStefano Zampini       rwork = NULL;
3146d1710679SStefano Zampini #endif
31478bec7fa6SStefano Zampini       thresh = 1.0;
314808122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
314908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
315008122e43SStefano 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));
315108122e43SStefano Zampini #else
315208122e43SStefano 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));
315308122e43SStefano Zampini #endif
315408122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
315508122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3156bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
315708122e43SStefano Zampini   } else {
315808122e43SStefano Zampini     lwork = 0;
315908122e43SStefano Zampini   }
316008122e43SStefano Zampini 
316108122e43SStefano Zampini   nv = 0;
3162d62866d3SStefano 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) */
3163d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
316408122e43SStefano Zampini   }
31654c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3166f6f667cfSStefano Zampini   if (allocated_S_St) {
3167f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3168f6f667cfSStefano Zampini   }
3169f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
317008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
317108122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
317208122e43SStefano Zampini #endif
31739162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
31749162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
31759162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
317608122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
31779162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
317808122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
317908122e43SStefano Zampini 
318008122e43SStefano Zampini   maxneigs = 0;
318172b8c272SStefano Zampini   cum = cumarray = 0;
31829162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
31839162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3184d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
318508122e43SStefano Zampini     const PetscInt *idxs;
318608122e43SStefano Zampini 
3187d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
318808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
318908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
319008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
319108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31929162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31939162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
319408122e43SStefano Zampini     }
3195d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
319608122e43SStefano Zampini   }
319708122e43SStefano Zampini 
319808122e43SStefano Zampini   if (mss) { /* multilevel */
319908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
320008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
320108122e43SStefano Zampini   }
320208122e43SStefano Zampini 
3203bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3204bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
320508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
320608122e43SStefano Zampini     const PetscInt *idxs;
32079d54b7f4SStefano Zampini     PetscReal      upper,lower;
3208862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
320908122e43SStefano Zampini     PetscBLASInt   B_N;
3210aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3211bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
321208122e43SStefano Zampini 
32139d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
32149d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3215bd2a564bSStefano Zampini       lower = uthresh;
32169d54b7f4SStefano Zampini     } else {
3217bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3218bd2a564bSStefano Zampini       upper = 1./uthresh;
32199d54b7f4SStefano Zampini       lower = 0.;
32209d54b7f4SStefano Zampini     }
3221862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3222ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3223f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3224bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3225bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3226bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3227bd2a564bSStefano Zampini       Mat T;
3228bd2a564bSStefano Zampini 
3229bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3230bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3231bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3232bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3233bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3234bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3235bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3236bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3237bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3238bd2a564bSStefano Zampini             PetscInt       nz,k;
3239bd2a564bSStefano Zampini             const PetscInt *idxs;
3240bd2a564bSStefano Zampini 
3241bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3242bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3243bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3244bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3245bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3246bd2a564bSStefano Zampini             }
3247bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3248bd2a564bSStefano Zampini           }
3249bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3250bd2a564bSStefano Zampini           break;
3251bd2a564bSStefano Zampini         }
3252bd2a564bSStefano Zampini       }
3253bd2a564bSStefano Zampini     }
3254bd2a564bSStefano Zampini 
3255f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3256bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3257aff50787SStefano Zampini         PetscInt j,k;
3258aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3259aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3260aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
326108122e43SStefano Zampini         }
326208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3263aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3264aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3265aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3266aff50787SStefano Zampini           }
326708122e43SStefano Zampini         }
326808122e43SStefano Zampini       } else {
326908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
327008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
327108122e43SStefano Zampini       }
32728bec7fa6SStefano Zampini     } else {
3273f6f667cfSStefano Zampini       S = Sarray + cumarray;
3274f6f667cfSStefano Zampini       St = Starray + cumarray;
32758bec7fa6SStefano Zampini     }
3276aff50787SStefano Zampini     /* see if we can save some work */
3277b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3278aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3279aff50787SStefano Zampini     }
3280aff50787SStefano Zampini 
3281b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3282aff50787SStefano Zampini       B_neigs = 0;
3283aff50787SStefano Zampini     } else {
3284bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
328508122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3286f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
32874c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
32889552c7c7SStefano Zampini         PetscInt     nmin_s;
3289bd2a564bSStefano Zampini         PetscBool    compute_range;
3290bd2a564bSStefano Zampini 
32919036ceccSStefano Zampini         B_neigs = 0;
3292bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3293bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
329408122e43SStefano Zampini 
3295fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
32969036ceccSStefano Zampini           PetscInt nc = 0;
3297d16cbb6bSStefano Zampini 
32989036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
32999036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
33009036ceccSStefano Zampini           }
33016080607fSStefano 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);
3302b7ab4a40SStefano Zampini         }
3303b7ab4a40SStefano Zampini 
330408122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3305b7ab4a40SStefano Zampini         if (compute_range) {
3306d16cbb6bSStefano Zampini 
3307d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3308bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
330908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33109d54b7f4SStefano 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));
331108122e43SStefano Zampini #else
33129d54b7f4SStefano 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));
331308122e43SStefano Zampini #endif
331443371fb9SStefano Zampini             ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3315bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33169036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3317bd2a564bSStefano Zampini             PetscReal bb[2];
3318bd2a564bSStefano Zampini 
3319bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3320bd2a564bSStefano Zampini             switch (recipe) {
3321bd2a564bSStefano Zampini             case 0:
3322bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3323bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3324bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3325bd2a564bSStefano 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));
3326bd2a564bSStefano Zampini #else
3327bd2a564bSStefano 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));
3328bd2a564bSStefano Zampini #endif
332943371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3330bd2a564bSStefano Zampini               break;
3331bd2a564bSStefano Zampini             case 1:
3332bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3333bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3334bd2a564bSStefano 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));
3335bd2a564bSStefano Zampini #else
3336bd2a564bSStefano 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));
3337bd2a564bSStefano Zampini #endif
333843371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3339bd2a564bSStefano Zampini               if (!scal) {
33409036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3341bd2a564bSStefano Zampini 
3342aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3343bd2a564bSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3344bd2a564bSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3345bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3346bd2a564bSStefano 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));
3347bd2a564bSStefano Zampini #else
3348bd2a564bSStefano 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));
3349bd2a564bSStefano Zampini #endif
335043371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3351bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3352bd2a564bSStefano Zampini               }
3353bd2a564bSStefano Zampini               break;
33549036ceccSStefano Zampini             case 2:
33559036ceccSStefano Zampini               if (scal) {
33569036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
33579036ceccSStefano Zampini                 bb[1] = 0;
33589036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33599036ceccSStefano 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));
33609036ceccSStefano Zampini #else
33619036ceccSStefano 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));
33629036ceccSStefano Zampini #endif
336343371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33649036ceccSStefano Zampini               } else {
33659036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
33669036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
33679036ceccSStefano Zampini 
33689036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
33699036ceccSStefano Zampini                 if (lthresh > 0.0) {
33709036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
33719036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
33729036ceccSStefano Zampini 
33739036ceccSStefano Zampini                   import = PETSC_TRUE;
33749036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33759036ceccSStefano 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));
33769036ceccSStefano Zampini #else
33779036ceccSStefano 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));
33789036ceccSStefano Zampini #endif
337943371fb9SStefano Zampini                   ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33809036ceccSStefano Zampini                 }
33819036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
33829036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
33839036ceccSStefano Zampini                 if (import) {
33849036ceccSStefano Zampini                   ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33859036ceccSStefano Zampini                   ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33869036ceccSStefano Zampini                 }
33879036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33889036ceccSStefano 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));
33899036ceccSStefano Zampini #else
33909036ceccSStefano 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));
33919036ceccSStefano Zampini #endif
339243371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33939036ceccSStefano Zampini                 B_neigs += B_neigs2;
33949036ceccSStefano Zampini               }
33959036ceccSStefano Zampini               break;
33969036ceccSStefano Zampini             case 3:
33979036ceccSStefano Zampini               if (scal) {
33989036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
33999036ceccSStefano Zampini               } else {
34009036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
34019036ceccSStefano Zampini               }
34029036ceccSStefano Zampini               if (!scal) {
34039036ceccSStefano Zampini                 bb[0] = uthresh;
34049036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34059036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34069036ceccSStefano 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));
34079036ceccSStefano Zampini #else
34089036ceccSStefano 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));
34099036ceccSStefano Zampini #endif
341043371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34119036ceccSStefano Zampini               }
34129036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34139036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34149036ceccSStefano Zampini 
34159036ceccSStefano Zampini                 B_IL = 1;
34169036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
34179036ceccSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
34189036ceccSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
34199036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34209036ceccSStefano 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));
34219036ceccSStefano Zampini #else
34229036ceccSStefano 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));
34239036ceccSStefano Zampini #endif
342443371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34259036ceccSStefano Zampini                 B_neigs += B_neigs2;
34269036ceccSStefano Zampini               }
34279036ceccSStefano Zampini               break;
342848cebe81SStefano Zampini             case 4:
342948cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
343048cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
343148cebe81SStefano 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));
343248cebe81SStefano Zampini #else
343348cebe81SStefano 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));
343448cebe81SStefano Zampini #endif
343543371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
343648cebe81SStefano Zampini               {
343748cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
343848cebe81SStefano Zampini 
343948cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
344048cebe81SStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
344148cebe81SStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
344248cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
344348cebe81SStefano 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));
344448cebe81SStefano Zampini #else
344548cebe81SStefano 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));
344648cebe81SStefano Zampini #endif
344743371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
344848cebe81SStefano Zampini                 B_neigs += B_neigs2;
344948cebe81SStefano Zampini               }
345048cebe81SStefano Zampini               break;
345180db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
345280db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
345380db8efeSStefano 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));
345480db8efeSStefano Zampini #else
345580db8efeSStefano 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));
345680db8efeSStefano Zampini #endif
345743371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
345880db8efeSStefano Zampini               {
345980db8efeSStefano Zampini                 PetscInt e,k,ne;
346080db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
346180db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
346280db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
346380db8efeSStefano Zampini                     eigs[ne] = eigs[e];
346480db8efeSStefano Zampini                     ne++;
346580db8efeSStefano Zampini                   }
346680db8efeSStefano Zampini                 }
346780db8efeSStefano Zampini                 ierr = PetscMemcpy(eigv,S,B_N*ne*sizeof(PetscScalar));CHKERRQ(ierr);
346880db8efeSStefano Zampini                 B_neigs = ne;
346980db8efeSStefano Zampini               }
347080db8efeSStefano Zampini               break;
3471bd2a564bSStefano Zampini             default:
3472bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3473bd2a564bSStefano Zampini               break;
3474bd2a564bSStefano Zampini             }
3475bd2a564bSStefano Zampini           }
3476bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3477d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3478d16cbb6bSStefano Zampini           B_IL = 1;
3479d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34809d54b7f4SStefano 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));
3481d16cbb6bSStefano Zampini #else
34829d54b7f4SStefano 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));
3483d16cbb6bSStefano Zampini #endif
348443371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3485b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3486b7ab4a40SStefano Zampini           PetscInt k;
3487b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3488b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3489b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3490b7ab4a40SStefano Zampini           nmin = nmax;
3491b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3492b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3493b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3494b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3495b7ab4a40SStefano Zampini           }
3496d16cbb6bSStefano Zampini         }
349708122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
349808122e43SStefano Zampini         if (B_ierr) {
34996c4ed002SBarry 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);
35006c4ed002SBarry 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);
35016c4ed002SBarry 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);
350208122e43SStefano Zampini         }
350308122e43SStefano Zampini 
350408122e43SStefano Zampini         if (B_neigs > nmax) {
3505fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35066080607fSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %D.\n",B_neigs,nmax);CHKERRQ(ierr);
3507fd14bc51SStefano Zampini           }
3508bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
350908122e43SStefano Zampini           B_neigs = nmax;
351008122e43SStefano Zampini         }
351108122e43SStefano Zampini 
35129552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35139552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35149036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
351508122e43SStefano Zampini 
35169d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3517bd2a564bSStefano Zampini             if (scal) {
3518bd2a564bSStefano Zampini               B_IU = nmin_s;
3519bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3520bd2a564bSStefano Zampini             } else {
3521f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35229d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3523bd2a564bSStefano Zampini             }
35249d54b7f4SStefano Zampini           } else {
35259d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35269d54b7f4SStefano Zampini             B_IU = nmin_s;
35279d54b7f4SStefano Zampini           }
3528fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35296080607fSStefano 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);
3530fd14bc51SStefano Zampini           }
3531bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35321ae86dd6SStefano Zampini             PetscInt j,k;
353308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35341ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35351ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35361ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
353708122e43SStefano Zampini               }
353808122e43SStefano Zampini             }
353908122e43SStefano Zampini           } else {
354008122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
354108122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
354208122e43SStefano Zampini           }
354308122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
354408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
35459d54b7f4SStefano 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));
354608122e43SStefano Zampini #else
35479d54b7f4SStefano 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));
354808122e43SStefano Zampini #endif
354943371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
355008122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
355108122e43SStefano Zampini           B_neigs += B_neigs2;
355208122e43SStefano Zampini         }
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         }
3558fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3559ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
356008122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
356108122e43SStefano Zampini             if (eigs[j] == 0.0) {
3562ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
356308122e43SStefano Zampini             } else {
35649d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3565ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
35669d54b7f4SStefano Zampini               } else {
35679d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
35689d54b7f4SStefano Zampini               }
3569fd14bc51SStefano Zampini             }
357008122e43SStefano Zampini           }
357108122e43SStefano Zampini         }
3572bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3573aff50787SStefano Zampini     }
35746c3e6151SStefano Zampini     /* change the basis back to the original one */
35756c3e6151SStefano Zampini     if (sub_schurs->change) {
357672b8c272SStefano Zampini       Mat change,phi,phit;
35776c3e6151SStefano Zampini 
357803dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
35796c3e6151SStefano Zampini         PetscInt ii;
35806c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
35816c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
35826c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3583684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3584684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3585684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3586684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3587684229deSStefano Zampini #else
35886c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3589684229deSStefano Zampini #endif
35906c3e6151SStefano Zampini           }
35916c3e6151SStefano Zampini         }
35926c3e6151SStefano Zampini       }
359372b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
35946c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
359572b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
35966c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
35976c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
35986c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
35996c3e6151SStefano Zampini     }
36008bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36018bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36029162d606SStefano Zampini     if (B_neigs) {
36039162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3604fd14bc51SStefano Zampini 
3605fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36069552c7c7SStefano Zampini         PetscInt ii;
36079552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3608ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36099552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3610ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3611ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3612ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3613ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3614ac47001eSStefano Zampini #else
3615ac47001eSStefano 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);
3616ac47001eSStefano Zampini #endif
36179552c7c7SStefano Zampini           }
36189552c7c7SStefano Zampini         }
3619fd14bc51SStefano Zampini       }
36209162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
36219162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36229162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36239162d606SStefano Zampini       cum++;
362408122e43SStefano Zampini     }
362508122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
362608122e43SStefano Zampini     /* shift for next computation */
362708122e43SStefano Zampini     cumarray += subset_size*subset_size;
362808122e43SStefano Zampini   }
3629fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3630fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3631fd14bc51SStefano Zampini   }
363208122e43SStefano Zampini 
363308122e43SStefano Zampini   if (mss) {
363408122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
363508122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3636f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3637f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3638f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
363908122e43SStefano Zampini   }
3640f6f667cfSStefano Zampini   if (allocated_S_St) {
3641f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3642f6f667cfSStefano Zampini   }
3643f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
364408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
364508122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
364608122e43SStefano Zampini #endif
364708122e43SStefano Zampini   if (pcbddc->dbg_flag) {
36481b968477SStefano Zampini     PetscInt maxneigs_r;
3649b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
36506080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %D\n",maxneigs_r);CHKERRQ(ierr);
365108122e43SStefano Zampini   }
365243371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
365308122e43SStefano Zampini   PetscFunctionReturn(0);
365408122e43SStefano Zampini }
3655b1b3d7a2SStefano Zampini 
3656c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3657c8587f34SStefano Zampini {
36588629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3659c8587f34SStefano Zampini   PetscErrorCode ierr;
3660c8587f34SStefano Zampini 
3661c8587f34SStefano Zampini   PetscFunctionBegin;
3662f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
36635e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3664c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3665c8587f34SStefano Zampini 
3666684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
36670fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3668684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3669c8587f34SStefano Zampini 
36708629588bSStefano Zampini   /*
36718629588bSStefano Zampini      Setup local correction and local part of coarse basis.
36728629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
36738629588bSStefano Zampini   */
367447f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
36758629588bSStefano Zampini 
36768629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
36778629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
36788629588bSStefano Zampini 
36798629588bSStefano Zampini   /* free */
36808629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3681c8587f34SStefano Zampini   PetscFunctionReturn(0);
3682c8587f34SStefano Zampini }
3683c8587f34SStefano Zampini 
3684674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3685674ae819SStefano Zampini {
3686674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3687674ae819SStefano Zampini   PetscErrorCode ierr;
3688674ae819SStefano Zampini 
3689674ae819SStefano Zampini   PetscFunctionBegin;
3690674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
369130368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3692674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3693785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3694674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3695f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3696f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3697785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
369863602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
369963602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3700674ae819SStefano Zampini   PetscFunctionReturn(0);
3701674ae819SStefano Zampini }
3702674ae819SStefano Zampini 
3703674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3704674ae819SStefano Zampini {
3705674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37064f1b2e48SStefano Zampini   PetscInt       i;
3707674ae819SStefano Zampini   PetscErrorCode ierr;
3708674ae819SStefano Zampini 
3709674ae819SStefano Zampini   PetscFunctionBegin;
37101e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
37111e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3712a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3713b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3714674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
371516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
37161dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3717674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3718669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3719fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
37209326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
37214f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37224f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
37234f1b2e48SStefano Zampini   }
3724e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37254f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3726e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3727c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37288af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37291c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3730674ae819SStefano Zampini   PetscFunctionReturn(0);
3731674ae819SStefano Zampini }
3732674ae819SStefano Zampini 
3733674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3734674ae819SStefano Zampini {
3735674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3736674ae819SStefano Zampini   PetscErrorCode ierr;
3737674ae819SStefano Zampini 
3738674ae819SStefano Zampini   PetscFunctionBegin;
3739674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
374058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3741ca92afb2SStefano Zampini     PetscScalar *array;
374206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
374306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
374458da7f69SStefano Zampini   }
3745674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3746674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
374715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
374815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3749674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3750674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3751674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
375206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3753674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3754674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
37558ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3756674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3757674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3758674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
37599326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
37609326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
37619326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3762f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3763727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
37640e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3765f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
376670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
376781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
37680369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
37691dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
37704f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
37718b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3772ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3773ca92afb2SStefano Zampini     PetscInt i;
3774ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3775ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3776ca92afb2SStefano Zampini     }
3777ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3778ca92afb2SStefano Zampini   }
37794f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3780674ae819SStefano Zampini   PetscFunctionReturn(0);
3781674ae819SStefano Zampini }
3782674ae819SStefano Zampini 
3783f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
37846bfb1811SStefano Zampini {
37856bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37866bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
37876bfb1811SStefano Zampini   VecType        impVecType;
37884f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
37896bfb1811SStefano Zampini   PetscErrorCode ierr;
37906bfb1811SStefano Zampini 
37916bfb1811SStefano Zampini   PetscFunctionBegin;
37924f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3793b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
37946bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3795e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3796e7b262bdSStefano Zampini   /* R nodes */
3797e7b262bdSStefano Zampini   old_size = -1;
3798e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3799e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3800e7b262bdSStefano Zampini   }
3801e7b262bdSStefano Zampini   if (n_R != old_size) {
3802e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3803e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38046bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
38056bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
38066bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
38076bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3808e7b262bdSStefano Zampini   }
3809e7b262bdSStefano Zampini   /* local primal dofs */
3810e7b262bdSStefano Zampini   old_size = -1;
3811e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3812e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3813e7b262bdSStefano Zampini   }
3814e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3815e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
381683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3817e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
38186bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3819e7b262bdSStefano Zampini   }
3820e7b262bdSStefano Zampini   /* local explicit constraints */
3821e7b262bdSStefano Zampini   old_size = -1;
3822e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3823e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3824e7b262bdSStefano Zampini   }
3825e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3826e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
382783b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
382883b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
382983b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
383083b7ccabSStefano Zampini   }
38316bfb1811SStefano Zampini   PetscFunctionReturn(0);
38326bfb1811SStefano Zampini }
38336bfb1811SStefano Zampini 
383447f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
383588ebb749SStefano Zampini {
383625084f0cSStefano Zampini   PetscErrorCode  ierr;
383725084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
383888ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
383988ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3840d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
384125084f0cSStefano Zampini   /* submatrices of local problem */
384280677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
384306656605SStefano Zampini   /* submatrices of local coarse problem */
384406656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
384525084f0cSStefano Zampini   /* working matrices */
384606656605SStefano Zampini   Mat             C_CR;
384725084f0cSStefano Zampini   /* additional working stuff */
384806656605SStefano Zampini   PC              pc_R;
3849c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
38505cbda25cSStefano Zampini   Vec             dummy_vec;
3851c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
385225084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
385306656605SStefano Zampini   PetscScalar     *work;
385406656605SStefano Zampini   PetscInt        *idx_V_B;
3855ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
385606656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3857ffd830a3SStefano Zampini 
385825084f0cSStefano Zampini   /* some shortcuts to scalars */
385906656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
386088ebb749SStefano Zampini 
386188ebb749SStefano Zampini   PetscFunctionBegin;
38629a962809SStefano 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");
386343371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
3864ffd830a3SStefano Zampini 
3865ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3866b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
38674f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3868b371cd4fSStefano Zampini   n_B = pcis->n_B;
3869b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
387088ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
387188ebb749SStefano Zampini 
387288ebb749SStefano Zampini   /* vertices in boundary numbering */
3873785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
38740e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
38756080607fSStefano Zampini   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",n_vertices,i);
387688ebb749SStefano Zampini 
387706656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3878019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
387906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
388006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
388106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
388206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
388306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
388406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
388506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
388606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
388706656605SStefano Zampini 
388806656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
388906656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
38902958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
389106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
389206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
389306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3894ffd830a3SStefano Zampini   lda_rhs = n_R;
3895a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
389606656605SStefano Zampini   if (isLU || isILU || isCHOL) {
389706656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3898b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3899df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3900d62866d3SStefano Zampini     MatFactorType      type;
3901d62866d3SStefano Zampini 
3902df4d28bfSStefano Zampini     F = reuse_solver->F;
39036816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3904d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3905ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
390622db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
390706656605SStefano Zampini   } else {
390806656605SStefano Zampini     F = NULL;
390906656605SStefano Zampini   }
391006656605SStefano Zampini 
3911c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3912c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3913c58f9fdbSStefano Zampini   if (F) {
3914ea799195SBarry Smith     MatSolverType solver;
3915c58f9fdbSStefano Zampini 
39163ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3917c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3918c58f9fdbSStefano Zampini   }
3919c58f9fdbSStefano Zampini 
3920ffd830a3SStefano Zampini   /* allocate workspace */
3921ffd830a3SStefano Zampini   n = 0;
3922ffd830a3SStefano Zampini   if (n_constraints) {
3923ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3924ffd830a3SStefano Zampini   }
3925ffd830a3SStefano Zampini   if (n_vertices) {
3926ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3927ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3928ffd830a3SStefano Zampini   }
39292a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39302a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39312a3a6641Sstefano_zampini   }
3932ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3933ffd830a3SStefano Zampini 
39345cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39355cbda25cSStefano Zampini   dummy_vec = NULL;
39365cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
3937c72cccf8SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec);CHKERRQ(ierr);
3938c72cccf8SStefano Zampini     ierr = VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE);CHKERRQ(ierr);
3939c72cccf8SStefano Zampini     ierr = VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name);CHKERRQ(ierr);
39405cbda25cSStefano Zampini   }
39415cbda25cSStefano Zampini 
394288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
394388ebb749SStefano Zampini   if (n_constraints) {
3944837cedc9SStefano Zampini     Mat         M3,C_B;
394506656605SStefano Zampini     IS          is_aux;
394680677318SStefano Zampini     PetscScalar *array,*array2;
394706656605SStefano Zampini 
3948f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
394980677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
395088ebb749SStefano Zampini 
395125084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
395225084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
39537dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
39547dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
395588ebb749SStefano Zampini 
395680677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
395780677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3958c58f9fdbSStefano Zampini     if (!sparserhs) {
3959ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
396088ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
396106656605SStefano Zampini         const PetscScalar *row_cmat_values;
396206656605SStefano Zampini         const PetscInt    *row_cmat_indices;
396306656605SStefano Zampini         PetscInt          size_of_constraint,j;
396488ebb749SStefano Zampini 
396506656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
396606656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3967ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
396806656605SStefano Zampini         }
396906656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
397006656605SStefano Zampini       }
3971c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3972c58f9fdbSStefano Zampini     } else {
3973c58f9fdbSStefano Zampini       Mat tC_CR;
3974c58f9fdbSStefano Zampini 
3975c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3976c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3977c58f9fdbSStefano Zampini         PetscScalar *aa;
3978c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3979c58f9fdbSStefano Zampini         PetscBool   done;
3980c58f9fdbSStefano Zampini 
3981c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
398213903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3983c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3984c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3985c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
398613903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3987c58f9fdbSStefano Zampini       } else {
3988c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3989c58f9fdbSStefano Zampini         tC_CR = C_CR;
3990c58f9fdbSStefano Zampini       }
3991c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3992c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3993c58f9fdbSStefano Zampini     }
3994ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
399506656605SStefano Zampini     if (F) {
3996a3df083aSStefano Zampini       if (need_benign_correction) {
3997df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3998a3df083aSStefano Zampini 
399972b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
400072b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
4001a3df083aSStefano Zampini       }
4002c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
4003a3df083aSStefano Zampini       if (need_benign_correction) {
4004a3df083aSStefano Zampini         PetscScalar        *marr;
4005df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4006a3df083aSStefano Zampini 
4007a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
40085cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40095cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40105cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40115cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40125cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40135cbda25cSStefano Zampini           }
40145cbda25cSStefano Zampini         } else {
4015a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
4016a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40175cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4018a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4019a3df083aSStefano Zampini           }
40205cbda25cSStefano Zampini         }
4021a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
4022a3df083aSStefano Zampini       }
402306656605SStefano Zampini     } else {
402480677318SStefano Zampini       PetscScalar *marr;
402580677318SStefano Zampini 
402680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
402706656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
4028ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4029ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
403006656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
403106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
403206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
403306656605SStefano Zampini       }
403480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
403506656605SStefano Zampini     }
4036c58f9fdbSStefano Zampini     if (sparserhs) {
4037c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4038c58f9fdbSStefano Zampini     }
4039c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
404080677318SStefano Zampini     if (!pcbddc->switch_static) {
404180677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
404280677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
404380677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
404480677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4045ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
404680677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
404780677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
404880677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
404980677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
405080677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
405180677318SStefano Zampini       }
405280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
405380677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
405472b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
405580677318SStefano Zampini     } else {
4056ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4057ffd830a3SStefano Zampini         IS dummy;
4058ffd830a3SStefano Zampini 
4059ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
40607dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
4061ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
4062ffd830a3SStefano Zampini       } else {
406380677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
406480677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4065ffd830a3SStefano Zampini       }
406625084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
406780677318SStefano Zampini     }
406880677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
406980677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
407080677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
407180677318SStefano Zampini     if (isCHOL) {
407280677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
407380677318SStefano Zampini     } else {
407425084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
407580677318SStefano Zampini     }
4076837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
407780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
4078837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
407972b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
4080837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
4081837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
4082f4ddd8eeSStefano Zampini   }
4083fc227af8SStefano Zampini 
4084fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
408588ebb749SStefano Zampini   if (n_vertices) {
408606656605SStefano Zampini     IS        is_aux;
4087c58f9fdbSStefano Zampini     PetscBool isseqaij;
40883a50541eSStefano Zampini 
4089b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
40906816873aSStefano Zampini       IS tis;
40916816873aSStefano Zampini 
40926816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
40936816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
40946816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
40956816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
40966816873aSStefano Zampini     } else {
40973a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
40986816873aSStefano Zampini     }
40997dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
41007dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
4101c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
4102c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
4103c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4104c58f9fdbSStefano Zampini     }
41057dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
410625084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
410788ebb749SStefano Zampini   }
410888ebb749SStefano Zampini 
410988ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4110f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
411106656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
411206656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
411306656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
411406656605SStefano Zampini     }
4115f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
411606656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
411706656605SStefano Zampini       PetscScalar *marray;
411806656605SStefano Zampini 
411906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
412006656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4121f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4122f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4123f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4124f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4125f4ddd8eeSStefano Zampini     }
4126f4ddd8eeSStefano Zampini   }
412706656605SStefano Zampini 
4128f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4129a6e023c1Sstefano_zampini     PetscScalar *marr;
413088ebb749SStefano Zampini 
4131a6e023c1Sstefano_zampini     /* memory size */
413206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4133a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4134a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4135a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4136a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4137a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
41388eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4139a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4140a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
414188ebb749SStefano Zampini     }
41423301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4143a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4144a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
41458eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4146a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
414788ebb749SStefano Zampini       }
414888ebb749SStefano Zampini     } else {
4149c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4150c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
41511b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4152c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4153c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4154c0553b1fSStefano Zampini       }
415588ebb749SStefano Zampini     }
415606656605SStefano Zampini   }
4157019a44ceSStefano Zampini 
415806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
41594f1b2e48SStefano Zampini   p0_lidx_I = NULL;
41604f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4161d12edf2fSStefano Zampini     const PetscInt *idxs;
4162d12edf2fSStefano Zampini 
4163d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
41644f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
41654f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
41664f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
41674f1b2e48SStefano Zampini     }
4168d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4169d12edf2fSStefano Zampini   }
4170d16cbb6bSStefano Zampini 
417106656605SStefano Zampini   /* vertices */
417206656605SStefano Zampini   if (n_vertices) {
4173c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
417416f15bc4SStefano Zampini 
4175af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
417604708bb6SStefano Zampini 
417716f15bc4SStefano Zampini     if (n_R) {
417814393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
417906656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
418016f15bc4SStefano Zampini       PetscScalar  *x,*y;
418106656605SStefano Zampini 
418221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
418314393ed6SStefano Zampini       if (need_benign_correction) {
418414393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
418514393ed6SStefano Zampini         IS                     is_p0;
418614393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
418714393ed6SStefano Zampini 
418814393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
418914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
419014393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
41916080607fSStefano 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);
419214393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
419314393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
41947dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
419514393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
419614393ed6SStefano Zampini       }
419714393ed6SStefano Zampini 
4198c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4199c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4200ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4201af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4202ffd830a3SStefano Zampini         } else {
4203ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4204ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4205ca92afb2SStefano Zampini           PetscInt       n;
4206ca92afb2SStefano Zampini           PetscBool      flg_row;
4207ffd830a3SStefano Zampini 
4208ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4209ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
42109d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4211ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4212ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4213ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4214ca92afb2SStefano Zampini             PetscInt j;
4215ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4216ffd830a3SStefano Zampini           }
4217ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4218ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4219ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4220ffd830a3SStefano Zampini         }
4221a3df083aSStefano Zampini         if (need_benign_correction) {
4222df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4223a3df083aSStefano Zampini           PetscScalar        *marr;
4224a3df083aSStefano Zampini 
4225a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
422614393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
422714393ed6SStefano Zampini 
422814393ed6SStefano Zampini                  | 0 0  0 | (V)
422914393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
423014393ed6SStefano Zampini                  | 0 0 -1 | (p0)
423114393ed6SStefano Zampini 
423214393ed6SStefano Zampini           */
4233df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
423414393ed6SStefano Zampini             const PetscScalar *vals;
423514393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
423614393ed6SStefano Zampini             PetscInt          n,j,nz;
423714393ed6SStefano Zampini 
4238df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4239df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
424014393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
424114393ed6SStefano Zampini             for (j=0;j<n;j++) {
424214393ed6SStefano Zampini               PetscScalar val = vals[j];
424314393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
424414393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
424514393ed6SStefano Zampini             }
424614393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4247df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
424814393ed6SStefano Zampini           }
424972b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
425072b8c272SStefano Zampini         }
4251c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4252c58f9fdbSStefano Zampini         Brhs = A_RV;
4253c58f9fdbSStefano Zampini       } else {
4254c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4255c58f9fdbSStefano Zampini 
4256c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4257fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4258c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4259c58f9fdbSStefano Zampini         } else {
4260c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4261c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4262c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4263c58f9fdbSStefano Zampini           A_RVT = A_VR;
4264c58f9fdbSStefano Zampini         }
4265c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4266c58f9fdbSStefano Zampini           PetscScalar *aa;
4267c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4268c58f9fdbSStefano Zampini           PetscBool   done;
4269c58f9fdbSStefano Zampini 
4270c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
427113903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4272c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4273c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4274c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
427513903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4276c58f9fdbSStefano Zampini         } else {
4277c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4278c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4279c58f9fdbSStefano Zampini         }
4280c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4281c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4282c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4283c58f9fdbSStefano Zampini       }
428472b8c272SStefano Zampini       if (F) {
428514393ed6SStefano Zampini         /* need to correct the rhs */
428672b8c272SStefano Zampini         if (need_benign_correction) {
428772b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
428872b8c272SStefano Zampini           PetscScalar        *marr;
428972b8c272SStefano Zampini 
4290c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
42915cbda25cSStefano Zampini           if (lda_rhs != n_R) {
42925cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
42935cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
42945cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
42955cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
42965cbda25cSStefano Zampini             }
42975cbda25cSStefano Zampini           } else {
4298a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4299a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43005cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4301a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4302a3df083aSStefano Zampini             }
43035cbda25cSStefano Zampini           }
4304c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4305a3df083aSStefano Zampini         }
4306c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4307c58f9fdbSStefano Zampini         if (restoreavr) {
4308c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4309c58f9fdbSStefano Zampini         }
431014393ed6SStefano Zampini         /* need to correct the solution */
4311a3df083aSStefano Zampini         if (need_benign_correction) {
4312df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4313a3df083aSStefano Zampini           PetscScalar        *marr;
4314a3df083aSStefano Zampini 
4315a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
43165cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43175cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43185cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43195cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
43205cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43215cbda25cSStefano Zampini             }
43225cbda25cSStefano Zampini           } else {
4323a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4324a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43255cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4326a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4327a3df083aSStefano Zampini             }
43285cbda25cSStefano Zampini           }
4329a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4330a3df083aSStefano Zampini         }
433106656605SStefano Zampini       } else {
4332c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
433306656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4334ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4335ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
433606656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
433706656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
433806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
433906656605SStefano Zampini         }
4340c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
434106656605SStefano Zampini       }
434280677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4343c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4344ffd830a3SStefano Zampini       /* S_VV and S_CV */
434506656605SStefano Zampini       if (n_constraints) {
434606656605SStefano Zampini         Mat B;
434780677318SStefano Zampini 
4348ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
434980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4350ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4351ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
435280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
435380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
435480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
435580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
435680677318SStefano Zampini         }
4357ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
435880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
435980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4360ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
436180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
436206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4363ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4364ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
436506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
436606656605SStefano Zampini       }
4367ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4368ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4369ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4370ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4371ffd830a3SStefano Zampini       }
437206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
437314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
437414393ed6SStefano Zampini       if (need_benign_correction) {
4375df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
437614393ed6SStefano Zampini         PetscScalar      *marr,*sums;
437714393ed6SStefano Zampini 
437814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4379f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4380df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
438114393ed6SStefano Zampini           const PetscScalar *vals;
438214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
438314393ed6SStefano Zampini           PetscInt          n,j,nz;
438414393ed6SStefano Zampini 
4385df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4386df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
438714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
438814393ed6SStefano Zampini             PetscInt k;
438914393ed6SStefano Zampini             sums[j] = 0.;
439014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
439114393ed6SStefano Zampini           }
439214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
439314393ed6SStefano Zampini           for (j=0;j<n;j++) {
439414393ed6SStefano Zampini             PetscScalar val = vals[j];
439514393ed6SStefano Zampini             PetscInt k;
439614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
439714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
439814393ed6SStefano Zampini             }
439914393ed6SStefano Zampini           }
440014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4401df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
440214393ed6SStefano Zampini         }
440314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4404f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
440514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
440614393ed6SStefano Zampini       }
440780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
440806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
440906656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
441006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
441106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
441206656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
441306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
441406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4415d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4416019a44ceSStefano Zampini     } else {
4417d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4418d16cbb6bSStefano Zampini     }
441921eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4420d16cbb6bSStefano Zampini 
442106656605SStefano Zampini     /* coarse basis functions */
442206656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
442316f15bc4SStefano Zampini       PetscScalar *y;
442416f15bc4SStefano Zampini 
4425ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
442606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
442706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
442806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
443006656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
443106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
443206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
443306656605SStefano Zampini 
443406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
44354f1b2e48SStefano Zampini         PetscInt j;
44364f1b2e48SStefano Zampini 
443706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
443806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
443906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
444006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
444106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
44424f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
444306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
444406656605SStefano Zampini       }
444506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
444606656605SStefano Zampini     }
444704708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
444804708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
444906656605SStefano Zampini   }
44505cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
445106656605SStefano Zampini 
445206656605SStefano Zampini   if (n_constraints) {
445306656605SStefano Zampini     Mat B;
445406656605SStefano Zampini 
4455ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
445606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
445780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
445806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
445906656605SStefano Zampini     if (n_vertices) {
446003dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
446180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
446280677318SStefano Zampini       } else {
446380677318SStefano Zampini         Mat S_VCt;
446480677318SStefano Zampini 
4465ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4466ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
446772b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4468ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4469ffd830a3SStefano Zampini         }
447080677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
447180677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
447280677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
447380677318SStefano Zampini       }
447406656605SStefano Zampini     }
447506656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
447606656605SStefano Zampini     /* coarse basis functions */
447706656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
447806656605SStefano Zampini       PetscScalar *y;
447906656605SStefano Zampini 
4480ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
448106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
448206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
448306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
448606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
448706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
44884f1b2e48SStefano Zampini         PetscInt j;
44894f1b2e48SStefano Zampini 
449006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
449106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
449206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
44954f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
449606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
449706656605SStefano Zampini       }
449806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
449906656605SStefano Zampini     }
450006656605SStefano Zampini   }
450180677318SStefano Zampini   if (n_constraints) {
450280677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
450380677318SStefano Zampini   }
45044f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
450572b8c272SStefano Zampini 
450672b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
450772b8c272SStefano Zampini   if (pcbddc->benign_n) {
450872b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
450972b8c272SStefano Zampini     IS          is_dummy;
451072b8c272SStefano Zampini     PetscScalar *data;
451172b8c272SStefano Zampini     PetscInt    j;
451272b8c272SStefano Zampini 
451372b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
45147dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
451572b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
451672b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
451786c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
451872b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
451972b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
452072b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
452172b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
452272b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
452372b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
452472b8c272SStefano Zampini       }
452572b8c272SStefano Zampini     }
452672b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
452772b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
452872b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
452972b8c272SStefano Zampini   }
4530019a44ceSStefano Zampini 
453106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
45323301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4533ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4534ffd830a3SStefano Zampini     PetscScalar *marray;
453506656605SStefano Zampini 
453606656605SStefano Zampini     if (n_constraints) {
4537ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
453806656605SStefano Zampini 
4539abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
454006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4541ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
454216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
454306656605SStefano Zampini       if (n_vertices) {
4544ffd830a3SStefano Zampini         Mat S_VCT;
454506656605SStefano Zampini 
454606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4547ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
454816f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
454906656605SStefano Zampini       }
4550ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
45515b782168SStefano Zampini     } else {
45525b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
455306656605SStefano Zampini     }
455416f15bc4SStefano Zampini     if (n_vertices && n_R) {
4555ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4556ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4557ffd830a3SStefano Zampini       PetscInt       n;
4558ffd830a3SStefano Zampini       PetscBool      flg_row;
455906656605SStefano Zampini 
4560ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4561af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4562ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4563ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4564ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4565ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4566ffd830a3SStefano Zampini         PetscInt j;
4567ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4568ffd830a3SStefano Zampini       }
4569ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4570ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4571ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
457206656605SStefano Zampini     }
457306656605SStefano Zampini 
4574ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4575abc8f43dSstefano_zampini     if (n_vertices) {
4576ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4577ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4578ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4579ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
458006656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
458106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
458206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
458306656605SStefano Zampini       }
4584ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4585abc8f43dSstefano_zampini     }
45865b782168SStefano Zampini     if (B_C) {
4587ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4588ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4589ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4590ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4591ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4592ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4593ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
459406656605SStefano Zampini       }
4595ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
45965b782168SStefano Zampini     }
459706656605SStefano Zampini     /* coarse basis functions */
459806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
459906656605SStefano Zampini       PetscScalar *y;
460006656605SStefano Zampini 
4601ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
460206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
460306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
460406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
460506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
460606656605SStefano Zampini       if (i<n_vertices) {
460706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
460806656605SStefano Zampini       }
460906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
461006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
461106656605SStefano Zampini 
461206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
461306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
461406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
461506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
461606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
461706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
461806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
461906656605SStefano Zampini       }
462006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
462106656605SStefano Zampini     }
4622ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4623ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
462406656605SStefano Zampini   }
4625a6e023c1Sstefano_zampini 
4626d62866d3SStefano Zampini   /* free memory */
462788ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
462806656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
462906656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
463006656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
463106656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4632d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4633d62866d3SStefano Zampini   if (n_vertices) {
4634d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4635d62866d3SStefano Zampini   }
4636d62866d3SStefano Zampini   if (n_constraints) {
4637d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4638d62866d3SStefano Zampini   }
463988ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
464088ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
464188ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4642d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
464388ebb749SStefano Zampini     Mat         coarse_sub_mat;
464425084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
464588ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
464688ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
464788ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
46488bec7fa6SStefano Zampini     Mat         C_B,CPHI;
46498bec7fa6SStefano Zampini     IS          is_dummy;
46508bec7fa6SStefano Zampini     Vec         mones;
465188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
465288ebb749SStefano Zampini     PetscReal   real_value;
465388ebb749SStefano Zampini 
4654a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4655a3df083aSStefano Zampini       Mat A;
4656a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
46577dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
46587dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
46597dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
46607dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4661a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4662a3df083aSStefano Zampini     } else {
466388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
466488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
466588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
466688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4667a3df083aSStefano Zampini     }
466888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
466988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4670ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
467188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
467288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
467388ebb749SStefano Zampini     }
467488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
467588ebb749SStefano Zampini 
467625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46773301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
467825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4679ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
468088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
468188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
468288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
468388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
468488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
468588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
468688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
468788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
468888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
468988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
469088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
469188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
469288ebb749SStefano Zampini     } else {
469388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
469488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
469588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
469688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
469788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
469888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
469988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
470088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
470188ebb749SStefano Zampini     }
470288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
470388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
470488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4705511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
47064f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4707fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4708d12edf2fSStefano Zampini       PetscScalar *data,*data2;
47094f1b2e48SStefano Zampini       PetscInt    j;
4710d12edf2fSStefano Zampini 
47114f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
47127dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4713d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
471486c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4715d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4716d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
47174f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
47184f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4719d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
47204f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
47214f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
47224f1b2e48SStefano Zampini         }
4723d12edf2fSStefano Zampini       }
4724d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4725d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4726d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4727d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4728d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4729d12edf2fSStefano Zampini     }
4730d12edf2fSStefano Zampini #if 0
4731d12edf2fSStefano Zampini   {
4732d12edf2fSStefano Zampini     PetscViewer viewer;
4733d12edf2fSStefano Zampini     char filename[256];
4734ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4735d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4736a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4737ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4738ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4739ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4740d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4741a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4742ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4743ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
474472b8c272SStefano Zampini     }
4745ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4746ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4747ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4748ffd830a3SStefano Zampini     }
4749ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4750ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4751ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4752ffd830a3SStefano Zampini     }
475372b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4754ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4755ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4756ffd830a3SStefano Zampini     }
4757fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4758fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4759fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4760fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4761fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4762fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4763fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4764fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4765fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4766fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4767d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4768d12edf2fSStefano Zampini   }
4769d12edf2fSStefano Zampini #endif
477081d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
47718bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
47721575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
477306656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
47748bec7fa6SStefano Zampini 
47758bec7fa6SStefano Zampini     /* check constraints */
4776a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
47777dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
47784f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
47798bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4780a00504b5SStefano Zampini     } else {
4781a00504b5SStefano Zampini       PetscScalar *data;
4782a00504b5SStefano Zampini       Mat         tmat;
4783a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4784a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4785a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4786a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4787a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4788a00504b5SStefano Zampini     }
47898bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
47908bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
47918bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
47928bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4793bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4794ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4795bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4796bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4797bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4798bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4799bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
480088ebb749SStefano Zampini     }
48018bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
48028bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
48038bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
48048bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
480525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
480688ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
480788ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
480888ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
480988ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
481088ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
481188ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
481288ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
481388ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
481488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
481588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4816ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
481788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
481888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
481988ebb749SStefano Zampini     }
482088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
482188ebb749SStefano Zampini   }
48228629588bSStefano Zampini   /* get back data */
48238629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
482443371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
482588ebb749SStefano Zampini   PetscFunctionReturn(0);
482688ebb749SStefano Zampini }
482788ebb749SStefano Zampini 
48287dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4829aa0d41d4SStefano Zampini {
4830d65f70fdSStefano Zampini   Mat            *work_mat;
4831d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4832d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4833c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4834aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4835aa0d41d4SStefano Zampini 
4836aa0d41d4SStefano Zampini   PetscFunctionBegin;
4837d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4838d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4839d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4840d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4841aa0d41d4SStefano Zampini 
4842d65f70fdSStefano Zampini   if (!rsorted) {
4843906d46d4SStefano Zampini     const PetscInt *idxs;
4844906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4845aa0d41d4SStefano Zampini 
4846d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4847d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4848d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4849d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4850aa0d41d4SStefano Zampini     }
4851d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4852d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4853d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4854d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4855aa0d41d4SStefano Zampini     }
4856d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4857d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4858d65f70fdSStefano Zampini   } else {
4859d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4860d65f70fdSStefano Zampini     isrow_s = isrow;
4861aa0d41d4SStefano Zampini   }
4862906d46d4SStefano Zampini 
4863d65f70fdSStefano Zampini   if (!csorted) {
4864d65f70fdSStefano Zampini     if (isrow == iscol) {
4865d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4866d65f70fdSStefano Zampini       iscol_s = isrow_s;
4867d65f70fdSStefano Zampini     } else {
4868d65f70fdSStefano Zampini       const PetscInt *idxs;
4869d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4870906d46d4SStefano Zampini 
4871d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4872d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4873d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4874d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4875d65f70fdSStefano Zampini       }
4876d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4877d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4878d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4879d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4880d65f70fdSStefano Zampini       }
4881d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4882d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4883d65f70fdSStefano Zampini     }
4884d65f70fdSStefano Zampini   } else {
4885d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4886d65f70fdSStefano Zampini     iscol_s = iscol;
4887d65f70fdSStefano Zampini   }
4888d65f70fdSStefano Zampini 
48897dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4890d65f70fdSStefano Zampini 
4891d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4892906d46d4SStefano Zampini     Mat      new_mat;
4893d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4894906d46d4SStefano Zampini 
4895d65f70fdSStefano Zampini     if (!rsorted) {
4896d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4897d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4898d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4899d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4900906d46d4SStefano Zampini       }
4901d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4902d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4903d65f70fdSStefano Zampini     } else {
4904d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4905906d46d4SStefano Zampini     }
4906d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4907d65f70fdSStefano Zampini 
4908d65f70fdSStefano Zampini     if (!csorted) {
4909d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4910d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4911d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4912d65f70fdSStefano Zampini       } else {
4913d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4914f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4915d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4916d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4917d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4918d65f70fdSStefano Zampini         }
4919d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4920d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4921d65f70fdSStefano Zampini       }
4922d65f70fdSStefano Zampini     } else {
4923d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4924d65f70fdSStefano Zampini     }
4925d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4926d65f70fdSStefano Zampini 
4927d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4928d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4929d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4930d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4931d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4932d65f70fdSStefano Zampini   }
4933d65f70fdSStefano Zampini 
4934d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4935d65f70fdSStefano Zampini   *B = work_mat[0];
4936d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4937d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4938d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4939d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4940d65f70fdSStefano Zampini }
4941d65f70fdSStefano Zampini 
49425e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4943aa0d41d4SStefano Zampini {
4944aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
49455e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4946022d8d2bSstefano_zampini   Mat            new_mat,lA;
49475e8657edSStefano Zampini   IS             is_local,is_global;
4948d65f70fdSStefano Zampini   PetscInt       local_size;
4949d65f70fdSStefano Zampini   PetscBool      isseqaij;
4950aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4951aa0d41d4SStefano Zampini 
4952aa0d41d4SStefano Zampini   PetscFunctionBegin;
4953aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
49545e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
49555e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4956b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4957aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
49587dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4959aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4960906d46d4SStefano Zampini 
4961906d46d4SStefano Zampini   /* check */
4962906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4963906d46d4SStefano Zampini     Vec       x,x_change;
4964906d46d4SStefano Zampini     PetscReal error;
4965906d46d4SStefano Zampini 
49665e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4967906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
49685e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4969e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4970e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4971d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
497288428137SStefano Zampini     if (!pcbddc->change_interior) {
497388428137SStefano Zampini       const PetscScalar *x,*y,*v;
497488428137SStefano Zampini       PetscReal         lerror = 0.;
497588428137SStefano Zampini       PetscInt          i;
497688428137SStefano Zampini 
497788428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
497888428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
497988428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
498088428137SStefano Zampini       for (i=0;i<local_size;i++)
498188428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
498288428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
498388428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
498488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
498588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
498688428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4987637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4988637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
49896080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",error);
4990637e8532SStefano Zampini         } else {
49916080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",error);
4992637e8532SStefano Zampini         }
4993637e8532SStefano Zampini       }
499488428137SStefano Zampini     }
4995e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4996e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4997906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4998906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4999637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5000637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
50016080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
5002637e8532SStefano Zampini       } else {
50036080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",error);
5004637e8532SStefano Zampini       }
5005637e8532SStefano Zampini     }
5006906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
5007906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5008906d46d4SStefano Zampini   }
5009906d46d4SStefano Zampini 
5010022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
5011022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
5012022d8d2bSstefano_zampini 
501322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
50149b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
501522d5777bSStefano Zampini   if (isseqaij) {
5016a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5017a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
5018022d8d2bSstefano_zampini     if (lA) {
5019022d8d2bSstefano_zampini       Mat work;
5020022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5021022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5022022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5023022d8d2bSstefano_zampini     }
5024aa0d41d4SStefano Zampini   } else {
5025a00504b5SStefano Zampini     Mat work_mat;
50261cf9b237SStefano Zampini 
5027a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5028aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5029a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
50301d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
5031022d8d2bSstefano_zampini     if (lA) {
5032022d8d2bSstefano_zampini       Mat work;
5033022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5034022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5035022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5036022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5037022d8d2bSstefano_zampini     }
5038aa0d41d4SStefano Zampini   }
50393301b35fSStefano Zampini   if (matis->A->symmetric_set) {
50403301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
5041e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
50423301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
5043e496cd5dSStefano Zampini #endif
50443301b35fSStefano Zampini   }
5045d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
5046aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
5047aa0d41d4SStefano Zampini }
5048aa0d41d4SStefano Zampini 
50498ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
5050a64d13efSStefano Zampini {
5051a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
5052a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5053d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
505453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
50553a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
50563a50541eSStefano Zampini   PetscInt        vbs,bs;
50576816873aSStefano Zampini   PetscBT         bitmask=NULL;
5058a64d13efSStefano Zampini   PetscErrorCode  ierr;
5059a64d13efSStefano Zampini 
5060a64d13efSStefano Zampini   PetscFunctionBegin;
5061b23d619eSStefano Zampini   /*
5062b23d619eSStefano Zampini     No need to setup local scatters if
5063b23d619eSStefano Zampini       - primal space is unchanged
5064b23d619eSStefano Zampini         AND
5065b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
5066b23d619eSStefano Zampini         AND
5067b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5068b23d619eSStefano Zampini   */
5069b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5070f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5071f4ddd8eeSStefano Zampini   }
5072f4ddd8eeSStefano Zampini   /* destroy old objects */
5073f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
5074f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
5075f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
5076a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5077b371cd4fSStefano Zampini   n_B = pcis->n_B;
5078b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5079b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
50803a50541eSStefano Zampini 
5081a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
50826816873aSStefano Zampini 
508353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5084b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
5085854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
5086a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
5087a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
50880e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
5089a64d13efSStefano Zampini     }
5090a64d13efSStefano Zampini 
5091a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
50924641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
50936816873aSStefano Zampini         idx_R_local[n_R++] = i;
5094a64d13efSStefano Zampini       }
5095a64d13efSStefano Zampini     }
5096df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5097df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
50986816873aSStefano Zampini 
5099df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5100df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
51016816873aSStefano Zampini   }
51023a50541eSStefano Zampini 
51033a50541eSStefano Zampini   /* Block code */
51043a50541eSStefano Zampini   vbs = 1;
51053a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
51063a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
51073a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
51083a50541eSStefano Zampini     PetscInt  *vary;
5109b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5110785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
51113a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
5112d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5113d3df7717SStefano 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 */
51140e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5115d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
51163a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
51173a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
51183a50541eSStefano Zampini           break;
51193a50541eSStefano Zampini         }
51203a50541eSStefano Zampini       }
5121d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5122d3df7717SStefano Zampini     } else {
5123d3df7717SStefano Zampini       /* Verify directly the R set */
5124d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5125d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5126d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5127d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5128d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5129d3df7717SStefano Zampini             break;
5130d3df7717SStefano Zampini           }
5131d3df7717SStefano Zampini         }
5132d3df7717SStefano Zampini       }
5133d3df7717SStefano Zampini     }
51343a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
51353a50541eSStefano Zampini       vbs = bs;
51363a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
51373a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
51383a50541eSStefano Zampini       }
51393a50541eSStefano Zampini     }
51403a50541eSStefano Zampini   }
51413a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5142b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5143df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
514453892102SStefano Zampini 
5145df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5146df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
514753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5148df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
514953892102SStefano Zampini   } else {
51503a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
515153892102SStefano Zampini   }
5152a64d13efSStefano Zampini 
5153a64d13efSStefano Zampini   /* print some info if requested */
5154a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5155a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5156a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51571575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5158a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
51596080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %D, dirichlet_size = %D, boundary_size = %D\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
51606080607fSStefano 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);
5161a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5162a64d13efSStefano Zampini   }
5163a64d13efSStefano Zampini 
5164a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5165b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
51666816873aSStefano Zampini     IS       is_aux1,is_aux2;
51676816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
51686816873aSStefano Zampini 
51693a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5170854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5171854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5172a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
51734641a718SStefano Zampini     for (i=0; i<n_D; i++) {
51744641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
51754641a718SStefano Zampini     }
5176a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5177a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
51784641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
51794641a718SStefano Zampini         aux_array1[j++] = i;
5180a64d13efSStefano Zampini       }
5181a64d13efSStefano Zampini     }
5182a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5183a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5184a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
51854641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
51864641a718SStefano Zampini         aux_array2[j++] = i;
5187a64d13efSStefano Zampini       }
5188a64d13efSStefano Zampini     }
5189a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5190a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
519135928de7SBarry Smith     ierr = VecScatterCreateWithData(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5192a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5193a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5194a64d13efSStefano Zampini 
51958eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5196785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5197a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
51984641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
51994641a718SStefano Zampini           aux_array1[j++] = i;
5200a64d13efSStefano Zampini         }
5201a64d13efSStefano Zampini       }
5202a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
520335928de7SBarry Smith       ierr = VecScatterCreateWithData(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5204a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5205a64d13efSStefano Zampini     }
52064641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
52073a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5208d62866d3SStefano Zampini   } else {
5209df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
52106816873aSStefano Zampini     IS                 tis;
52116816873aSStefano Zampini     PetscInt           schur_size;
52126816873aSStefano Zampini 
5213df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
52146816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
521535928de7SBarry Smith     ierr = VecScatterCreateWithData(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
52166816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
52176816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
52186816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
521935928de7SBarry Smith       ierr = VecScatterCreateWithData(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
52206816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5221d62866d3SStefano Zampini     }
5222d62866d3SStefano Zampini   }
5223a64d13efSStefano Zampini   PetscFunctionReturn(0);
5224a64d13efSStefano Zampini }
5225a64d13efSStefano Zampini 
5226304d26faSStefano Zampini 
5227684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5228304d26faSStefano Zampini {
5229304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5230304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5231304d26faSStefano Zampini   PC             pc_temp;
5232304d26faSStefano Zampini   Mat            A_RR;
5233f4ddd8eeSStefano Zampini   MatReuse       reuse;
5234304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5235304d26faSStefano Zampini   PetscReal      value;
523604708bb6SStefano Zampini   PetscInt       n_D,n_R;
523735529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
5238304d26faSStefano Zampini   PetscErrorCode ierr;
5239e604994aSStefano Zampini   /* prefixes stuff */
5240312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5241e604994aSStefano Zampini   size_t         len;
5242304d26faSStefano Zampini 
5243304d26faSStefano Zampini   PetscFunctionBegin;
524443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5245e604994aSStefano Zampini   /* compute prefixes */
5246e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5247e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5248e604994aSStefano Zampini   if (!pcbddc->current_level) {
5249a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5250a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5251a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5252a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5253e604994aSStefano Zampini   } else {
525435529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5255e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5256e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5257312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5258312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5259a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
526034d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
526134d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5262a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5263a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5264a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5265a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5266e604994aSStefano Zampini   }
5267e604994aSStefano Zampini 
5268304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5269684f6988SStefano Zampini   if (dirichlet) {
5270d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5271450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
52726080607fSStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
5273450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5274a3df083aSStefano Zampini         Mat    A_IIn;
5275a3df083aSStefano Zampini 
5276a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5277a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5278a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5279a3df083aSStefano Zampini       }
5280450f8f5eSStefano Zampini     }
52813301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
52823301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
5283964fefecSStefano Zampini     }
5284ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5285964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
5286304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
5287cd18cfedSStefano Zampini       void (*f)(void) = 0;
5288cd18cfedSStefano Zampini 
5289304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5290304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5291304d26faSStefano Zampini       /* default */
5292304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5293e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
52949577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5295304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
52969577ea80SStefano Zampini       if (issbaij) {
52979577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
52989577ea80SStefano Zampini       } else {
5299304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
53009577ea80SStefano Zampini       }
5301399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure);CHKERRQ(ierr);
5302304d26faSStefano Zampini       /* Allow user's customization */
5303304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5304cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5305cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5306cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5307cd18cfedSStefano Zampini         const PetscInt *idxs;
5308cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5309cd18cfedSStefano Zampini 
5310cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5311cd18cfedSStefano Zampini         ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5312cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5313cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5314cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5315cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5316cd18cfedSStefano Zampini           }
5317cd18cfedSStefano Zampini         }
5318cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5319cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5320cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5321cd18cfedSStefano Zampini       }
5322304d26faSStefano Zampini     }
53233007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(pcis->A_II,((PetscObject)pcbddc->ksp_D)->prefix);CHKERRQ(ierr);
5324d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5325b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5326df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5327d62866d3SStefano Zampini 
5328df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5329d5574798SStefano Zampini     }
5330304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5331304d26faSStefano Zampini     if (!n_D) {
5332304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5333304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5334304d26faSStefano Zampini     }
5335304d26faSStefano Zampini     /* set ksp_D into pcis data */
5336304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5337304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5338304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5339684f6988SStefano Zampini   }
5340304d26faSStefano Zampini 
5341304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5342684f6988SStefano Zampini   A_RR = 0;
5343684f6988SStefano Zampini   if (neumann) {
5344d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
534504708bb6SStefano Zampini     PetscInt        ibs,mbs;
53460aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
534704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
53480aa714b2SStefano Zampini 
53490aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
53500aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
53510aa714b2SStefano Zampini       IS iP;
53520aa714b2SStefano Zampini 
53530aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
53540aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
53550aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
53560aa714b2SStefano Zampini     }
5357f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
53588ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5359f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5360f4ddd8eeSStefano Zampini       PetscInt nn_R;
536181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5362f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5363f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5364f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5365f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5366f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5367f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5368f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5369727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5370f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5371f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5372f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5373f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5374f4ddd8eeSStefano Zampini         }
5375f4ddd8eeSStefano Zampini       }
5376f4ddd8eeSStefano Zampini       /* last check */
5377d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5378f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5379f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5380f4ddd8eeSStefano Zampini       }
5381f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5382f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5383f4ddd8eeSStefano Zampini     }
5384a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5385af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5386af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
538704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
538804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
538904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
539004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
539104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5392af732b37SStefano Zampini       } else {
5393511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
53946816873aSStefano Zampini       }
539504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
539604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
539704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
539804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
539904708bb6SStefano Zampini       } else {
5400511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
540104708bb6SStefano Zampini       }
540204708bb6SStefano Zampini     }
5403a00504b5SStefano Zampini     /* extract A_RR */
54040aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5405a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5406a00504b5SStefano Zampini 
5407a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
540816e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5409a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
541016e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
541116e386b8SStefano Zampini         } else {
54127dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5413a00504b5SStefano Zampini         }
5414a00504b5SStefano Zampini       } else {
5415a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5416a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5417a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5418a00504b5SStefano Zampini       }
5419a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
54207dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
542116e386b8SStefano Zampini     }
54223301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
54233301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
54246816873aSStefano Zampini     }
5425f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5426cd18cfedSStefano Zampini       void (*f)(void) = 0;
5427cd18cfedSStefano Zampini 
5428304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5429304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5430304d26faSStefano Zampini       /* default */
5431304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5432e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5433304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
54349577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
54359577ea80SStefano Zampini       if (issbaij) {
54369577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
54379577ea80SStefano Zampini       } else {
5438304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
54399577ea80SStefano Zampini       }
5440399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure);CHKERRQ(ierr);
5441304d26faSStefano Zampini       /* Allow user's customization */
5442304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5443cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5444cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5445cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5446cd18cfedSStefano Zampini         const PetscInt *idxs;
5447cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5448cd18cfedSStefano Zampini 
5449cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5450cd18cfedSStefano Zampini         ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5451cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5452cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5453cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5454cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5455cd18cfedSStefano Zampini           }
5456cd18cfedSStefano Zampini         }
5457cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5458cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5459cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5460cd18cfedSStefano Zampini       }
5461304d26faSStefano Zampini     }
5462304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5463304d26faSStefano Zampini     if (!n_R) {
5464304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5465304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5466304d26faSStefano Zampini     }
54673007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix);CHKERRQ(ierr);
54685cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5469df4d28bfSStefano Zampini     /* Reuse solver if it is present */
54700aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5471df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5472d62866d3SStefano Zampini 
5473df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5474d62866d3SStefano Zampini     }
5475684f6988SStefano Zampini   }
5476304d26faSStefano Zampini 
5477684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5478684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54791575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5480684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5481684f6988SStefano Zampini   }
5482c7017625SStefano Zampini 
5483c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
548435529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5485c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5486c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5487c7017625SStefano Zampini   }
5488c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
548935529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5490c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5491c7017625SStefano Zampini   }
5492c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
549335529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5494c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5495c7017625SStefano Zampini   }
5496c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5497c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5498684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
54990fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
55000fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
55010fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
55020fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
55030fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5504e604994aSStefano 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);
550535529e7bSStefano Zampini       if (check_corr) {
5506c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5507c7017625SStefano Zampini       }
5508304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5509304d26faSStefano Zampini     }
5510684f6988SStefano Zampini     if (neumann) { /* Neumann */
55110fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
55120fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
55130fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
55140fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
55150fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5516e604994aSStefano 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);
551735529e7bSStefano Zampini       if (check_corr) {
5518c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5519c7017625SStefano Zampini       }
5520304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5521304d26faSStefano Zampini     }
5522684f6988SStefano Zampini   }
55235cbda25cSStefano Zampini   /* free Neumann problem's matrix */
55245cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
552543371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5526304d26faSStefano Zampini   PetscFunctionReturn(0);
5527304d26faSStefano Zampini }
5528304d26faSStefano Zampini 
552980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5530674ae819SStefano Zampini {
5531674ae819SStefano Zampini   PetscErrorCode  ierr;
5532674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5533be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5534b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5535674ae819SStefano Zampini 
5536674ae819SStefano Zampini   PetscFunctionBegin;
5537b334f244SStefano Zampini   if (!reuse_solver) {
553880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
553920c7b377SStefano Zampini   }
554080677318SStefano Zampini   if (!pcbddc->switch_static) {
554180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
554280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
554380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
554420c7b377SStefano Zampini     }
5545b334f244SStefano Zampini     if (!reuse_solver) {
554680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
554780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
554820c7b377SStefano Zampini     } else {
5549df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5550be83ff47SStefano Zampini 
5551df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5552df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
555320c7b377SStefano Zampini     }
5554be83ff47SStefano Zampini   } else {
555580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
555680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
555780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
555880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
555980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
556080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
556180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
556280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
556380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5564674ae819SStefano Zampini     }
5565674ae819SStefano Zampini   }
5566b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
556780677318SStefano Zampini     if (applytranspose) {
556880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
556980677318SStefano Zampini     } else {
557080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
557180677318SStefano Zampini     }
5572be83ff47SStefano Zampini   } else {
5573df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5574be83ff47SStefano Zampini 
5575be83ff47SStefano Zampini     if (applytranspose) {
5576df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5577be83ff47SStefano Zampini     } else {
5578df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5579be83ff47SStefano Zampini     }
5580be83ff47SStefano Zampini   }
558180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
558280677318SStefano Zampini   if (!pcbddc->switch_static) {
5583b334f244SStefano Zampini     if (!reuse_solver) {
558480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
558580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5586be83ff47SStefano Zampini     } else {
5587df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5588be83ff47SStefano Zampini 
5589df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5590df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5591be83ff47SStefano Zampini     }
559280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
559380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
559480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
559580677318SStefano Zampini     }
559680677318SStefano Zampini   } else {
559780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
559880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
559980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
560080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
560180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
560280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
560380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
560480677318SStefano Zampini     }
560580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
560680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
560780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
560880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5609674ae819SStefano Zampini   }
5610674ae819SStefano Zampini   PetscFunctionReturn(0);
5611674ae819SStefano Zampini }
5612674ae819SStefano Zampini 
5613dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5614dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5615674ae819SStefano Zampini {
5616674ae819SStefano Zampini   PetscErrorCode ierr;
5617674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5618674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5619674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5620674ae819SStefano Zampini 
5621674ae819SStefano Zampini   PetscFunctionBegin;
5622dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
56234fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5624dc359a40SStefano Zampini     if (applytranspose) {
5625674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
56268eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5627dc359a40SStefano Zampini     } else {
5628674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5629674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
563015aaf578SStefano Zampini     }
56314fee134fSStefano Zampini   } else {
56324fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
56334fee134fSStefano Zampini   }
5634efc2fbd9SStefano Zampini 
5635efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
56364f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5637efc2fbd9SStefano Zampini     PetscScalar *array;
56384f1b2e48SStefano Zampini     PetscInt    j;
5639efc2fbd9SStefano Zampini 
5640efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
56414f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5642efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5643efc2fbd9SStefano Zampini   }
5644efc2fbd9SStefano Zampini 
564512edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
564612edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
564712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
564812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
564912edc857SStefano Zampini 
56509f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
565112edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
565251694757SStefano Zampini     Mat          coarse_mat;
5653964fefecSStefano Zampini     Vec          rhs,sol;
565451694757SStefano Zampini     MatNullSpace nullsp;
565527b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5656964fefecSStefano Zampini 
565727b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
565827b6a85dSStefano Zampini       PC        coarse_pc;
565927b6a85dSStefano Zampini 
566027b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
566127b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
566227b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
566327b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
566427b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
566527b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
56663bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
566727b6a85dSStefano Zampini       }
566827b6a85dSStefano Zampini     }
5669964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5670964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
567151694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
567212edc857SStefano Zampini     if (applytranspose) {
56739a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5674964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
56759bfcb8eaSStefano Zampini       ierr = MatGetTransposeNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
56769bfcb8eaSStefano Zampini       if (nullsp) {
56779bfcb8eaSStefano Zampini         ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
56789bfcb8eaSStefano Zampini       }
56792701bc32SStefano Zampini     } else {
56809bfcb8eaSStefano Zampini       ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
56811f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
56822701bc32SStefano Zampini         PC        coarse_pc;
56832701bc32SStefano Zampini 
56849bfcb8eaSStefano Zampini         if (nullsp) {
56859bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
56869bfcb8eaSStefano Zampini         }
56872701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
56882701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
56893e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
56902701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
569112edc857SStefano Zampini       } else {
5692964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
56939bfcb8eaSStefano Zampini         if (nullsp) {
56949bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
56959bfcb8eaSStefano Zampini         }
569612edc857SStefano Zampini       }
56972701bc32SStefano Zampini     }
56981d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
569927b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
570027b6a85dSStefano Zampini       PC        coarse_pc;
570127b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
570227b6a85dSStefano Zampini 
570327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
570427b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
570527b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
57063bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
570727b6a85dSStefano Zampini     }
570812edc857SStefano Zampini   }
5709674ae819SStefano Zampini 
5710674ae819SStefano Zampini   /* Local solution on R nodes */
57114fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
571280677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
57139f00e9b4SStefano Zampini   }
57149f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
57159f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
571612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5717674ae819SStefano Zampini 
57184fee134fSStefano Zampini   /* Sum contributions from the two levels */
57194fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5720dc359a40SStefano Zampini     if (applytranspose) {
5721dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5722dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5723dc359a40SStefano Zampini     } else {
5724674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
57258eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5726dc359a40SStefano Zampini     }
5727efc2fbd9SStefano Zampini     /* store p0 */
57284f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5729efc2fbd9SStefano Zampini       PetscScalar *array;
57304f1b2e48SStefano Zampini       PetscInt    j;
5731efc2fbd9SStefano Zampini 
5732efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
57334f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5734efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5735efc2fbd9SStefano Zampini     }
57364fee134fSStefano Zampini   } else { /* expand the coarse solution */
57374fee134fSStefano Zampini     if (applytranspose) {
57384fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
57394fee134fSStefano Zampini     } else {
57404fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
57414fee134fSStefano Zampini     }
57424fee134fSStefano Zampini   }
5743674ae819SStefano Zampini   PetscFunctionReturn(0);
5744674ae819SStefano Zampini }
5745674ae819SStefano Zampini 
574612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5747674ae819SStefano Zampini {
5748674ae819SStefano Zampini   PetscErrorCode ierr;
5749674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
575058da7f69SStefano Zampini   PetscScalar    *array;
575112edc857SStefano Zampini   Vec            from,to;
5752674ae819SStefano Zampini 
5753674ae819SStefano Zampini   PetscFunctionBegin;
575412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
575512edc857SStefano Zampini     from = pcbddc->coarse_vec;
575612edc857SStefano Zampini     to = pcbddc->vec1_P;
575712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
575812edc857SStefano Zampini       Vec tvec;
575958da7f69SStefano Zampini 
576058da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
576158da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
576212edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
576358da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
576458da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
576558da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
576612edc857SStefano Zampini     }
576712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
576812edc857SStefano Zampini     from = pcbddc->vec1_P;
576912edc857SStefano Zampini     to = pcbddc->coarse_vec;
577012edc857SStefano Zampini   }
577112edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5772674ae819SStefano Zampini   PetscFunctionReturn(0);
5773674ae819SStefano Zampini }
5774674ae819SStefano Zampini 
577512edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5776674ae819SStefano Zampini {
5777674ae819SStefano Zampini   PetscErrorCode ierr;
5778674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
577958da7f69SStefano Zampini   PetscScalar    *array;
578012edc857SStefano Zampini   Vec            from,to;
5781674ae819SStefano Zampini 
5782674ae819SStefano Zampini   PetscFunctionBegin;
578312edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
578412edc857SStefano Zampini     from = pcbddc->coarse_vec;
578512edc857SStefano Zampini     to = pcbddc->vec1_P;
578612edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
578712edc857SStefano Zampini     from = pcbddc->vec1_P;
578812edc857SStefano Zampini     to = pcbddc->coarse_vec;
578912edc857SStefano Zampini   }
579012edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
579112edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
579212edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
579312edc857SStefano Zampini       Vec tvec;
579458da7f69SStefano Zampini 
579512edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
579658da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
579758da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
579858da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
579958da7f69SStefano Zampini     }
580058da7f69SStefano Zampini   } else {
580158da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
580258da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
580312edc857SStefano Zampini     }
580412edc857SStefano Zampini   }
5805674ae819SStefano Zampini   PetscFunctionReturn(0);
5806674ae819SStefano Zampini }
5807674ae819SStefano Zampini 
5808984c4197SStefano Zampini /* uncomment for testing purposes */
5809984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5810674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5811674ae819SStefano Zampini {
5812674ae819SStefano Zampini   PetscErrorCode    ierr;
5813674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5814674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5815674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5816984c4197SStefano Zampini   /* one and zero */
5817984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5818984c4197SStefano Zampini   /* space to store constraints and their local indices */
58199162d606SStefano Zampini   PetscScalar       *constraints_data;
58209162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
58219162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
58229162d606SStefano Zampini   PetscInt          *constraints_n;
5823984c4197SStefano Zampini   /* iterators */
5824b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5825984c4197SStefano Zampini   /* BLAS integers */
5826e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5827e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5828c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5829727cdba6SStefano Zampini   /* reuse */
58300e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
58310e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5832984c4197SStefano Zampini   /* change of basis */
5833b3d85658SStefano Zampini   PetscBool         qr_needed;
58349162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5835984c4197SStefano Zampini   /* auxiliary stuff */
583664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
58378a0068c3SStefano Zampini   PetscInt          ncc;
5838984c4197SStefano Zampini   /* some quantities */
583945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5840a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
584157715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
5842984c4197SStefano Zampini 
5843674ae819SStefano Zampini   PetscFunctionBegin;
584457715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
58458e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
58468e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
58478e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
584816909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5849088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5850088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
58510e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
58520e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
58530e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
58540e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
58550e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5856088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5857cf5a6209SStefano Zampini 
5858cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
58599162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5860cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5861cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5862cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5863cf5a6209SStefano Zampini     PetscScalar  *array;
5864cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5865cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5866674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5867b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5868674ae819SStefano Zampini     PetscScalar  *work;
5869674ae819SStefano Zampini     PetscReal    *singular_vals;
5870674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5871674ae819SStefano Zampini     PetscReal    *rwork;
5872674ae819SStefano Zampini #endif
5873674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5874674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5875674ae819SStefano Zampini #else
5876964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5877964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5878674ae819SStefano Zampini #endif
5879674ae819SStefano Zampini 
5880674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5881d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5882e4d548c7SStefano Zampini     /* print some info */
58835c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5884e4d548c7SStefano Zampini       PetscInt nv;
5885e4d548c7SStefano Zampini 
5886c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5887e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5888e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5889e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
58906080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
58916080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
58926080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5893e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5894e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5895e4d548c7SStefano Zampini     }
5896e4d548c7SStefano Zampini 
5897d06fc5fdSStefano Zampini     /* free unneeded index sets */
5898d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5899d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5900674ae819SStefano Zampini     }
5901d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5902d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5903d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5904d06fc5fdSStefano Zampini       }
5905d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5906d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5907d06fc5fdSStefano Zampini     }
5908d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5909d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5910d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5911d06fc5fdSStefano Zampini       }
5912d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5913d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5914d06fc5fdSStefano Zampini     }
591570022509SStefano Zampini 
5916674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5917674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5918674ae819SStefano Zampini     if (nearnullsp) {
5919674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5920f4ddd8eeSStefano Zampini       /* remove any stored info */
5921f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5922f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5923f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5924f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5925f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5926473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5927f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5928f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5929f4ddd8eeSStefano Zampini       }
5930984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5931984c4197SStefano Zampini       nnsp_size = 0;
5932674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5933674ae819SStefano Zampini     }
5934984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5935984c4197SStefano Zampini     max_constraints = nnsp_size;
5936984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5937984c4197SStefano Zampini 
5938674ae819SStefano Zampini     /*
5939674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
59409162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
59419162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
59429162d606SStefano Zampini          There can be multiple constraints per connected component
5943674ae819SStefano Zampini                                                                                                                                                            */
5944674ae819SStefano Zampini     n_vertices = 0;
5945674ae819SStefano Zampini     if (ISForVertices) {
5946674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5947674ae819SStefano Zampini     }
59489162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
59499162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
59509162d606SStefano Zampini 
59519162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
59529162d606SStefano Zampini     total_counts *= max_constraints;
5953674ae819SStefano Zampini     total_counts += n_vertices;
59544641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
59559162d606SStefano Zampini 
5956674ae819SStefano Zampini     total_counts = 0;
5957674ae819SStefano Zampini     max_size_of_constraint = 0;
5958674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
59599162d606SStefano Zampini       IS used_is;
5960674ae819SStefano Zampini       if (i<n_ISForEdges) {
59619162d606SStefano Zampini         used_is = ISForEdges[i];
5962674ae819SStefano Zampini       } else {
59639162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5964674ae819SStefano Zampini       }
59659162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5966674ae819SStefano Zampini       total_counts += j;
5967674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5968674ae819SStefano Zampini     }
59699162d606SStefano 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);
59709162d606SStefano Zampini 
5971984c4197SStefano Zampini     /* get local part of global near null space vectors */
5972785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5973984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5974984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5975e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5976e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5977984c4197SStefano Zampini     }
5978674ae819SStefano Zampini 
5979242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5980242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5981a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5982242a89d7SStefano Zampini 
5983984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5984a773dcb8SStefano Zampini     if (!skip_lapack) {
5985674ae819SStefano Zampini       PetscScalar temp_work;
5986911cabfeSStefano Zampini 
5987674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5988984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5989785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5990785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5991785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5992674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5993785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5994674ae819SStefano Zampini #endif
5995674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5996c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5997c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5998674ae819SStefano Zampini       lwork = -1;
5999674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6000674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6001c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6002674ae819SStefano Zampini #else
6003c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6004674ae819SStefano Zampini #endif
6005674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
6006984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
6007674ae819SStefano Zampini #else /* on missing GESVD */
6008674ae819SStefano Zampini       /* SVD */
6009674ae819SStefano Zampini       PetscInt max_n,min_n;
6010674ae819SStefano Zampini       max_n = max_size_of_constraint;
6011984c4197SStefano Zampini       min_n = max_constraints;
6012984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
6013674ae819SStefano Zampini         min_n = max_size_of_constraint;
6014984c4197SStefano Zampini         max_n = max_constraints;
6015674ae819SStefano Zampini       }
6016785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
6017674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6018785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
6019674ae819SStefano Zampini #endif
6020674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
6021674ae819SStefano Zampini       lwork = -1;
6022e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
6023e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
6024b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
6025674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6026674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
60279162d606SStefano 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));
6028674ae819SStefano Zampini #else
60299162d606SStefano 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));
6030674ae819SStefano Zampini #endif
6031674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
6032984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
6033984c4197SStefano Zampini #endif /* on missing GESVD */
6034674ae819SStefano Zampini       /* Allocate optimal workspace */
6035674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
6036854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
6037674ae819SStefano Zampini     }
6038674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6039674ae819SStefano Zampini     total_counts = 0;
60409162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
60419162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6042674ae819SStefano Zampini     /* vertices */
60439162d606SStefano Zampini     if (n_vertices) {
6044674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
60459162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
6046674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
60479162d606SStefano Zampini         constraints_n[total_counts] = 1;
60489162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
60499162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
60509162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6051674ae819SStefano Zampini         total_counts++;
6052674ae819SStefano Zampini       }
6053674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6054674ae819SStefano Zampini       n_vertices = total_counts;
6055674ae819SStefano Zampini     }
6056984c4197SStefano Zampini 
6057674ae819SStefano Zampini     /* edges and faces */
60589162d606SStefano Zampini     total_counts_cc = total_counts;
6059911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
60609162d606SStefano Zampini       IS        used_is;
60619162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
60629162d606SStefano Zampini 
6063911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
60649162d606SStefano Zampini         used_is = ISForEdges[ncc];
6065984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6066674ae819SStefano Zampini       } else {
60679162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6068984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6069674ae819SStefano Zampini       }
6070674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
60719162d606SStefano Zampini 
60729162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
60739162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6074984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6075984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6076674ae819SStefano Zampini       if (nnsp_has_cnst) {
60775b08dc53SStefano Zampini         PetscScalar quad_value;
60789162d606SStefano Zampini 
60799162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
60809162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
60819162d606SStefano Zampini 
6082a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6083674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6084a773dcb8SStefano Zampini         } else {
6085a773dcb8SStefano Zampini           quad_value = 1.0;
6086a773dcb8SStefano Zampini         }
6087674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
60889162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6089674ae819SStefano Zampini         }
60909162d606SStefano Zampini         temp_constraints++;
6091674ae819SStefano Zampini         total_counts++;
6092674ae819SStefano Zampini       }
6093674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6094984c4197SStefano Zampini         PetscReal real_value;
60959162d606SStefano Zampini         PetscScalar *ptr_to_data;
60969162d606SStefano Zampini 
6097984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
60989162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6099674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
61009162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6101674ae819SStefano Zampini         }
6102984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
6103984c4197SStefano Zampini         /* check if array is null on the connected component */
6104e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
61059162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
610657715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6107674ae819SStefano Zampini           temp_constraints++;
6108674ae819SStefano Zampini           total_counts++;
61099162d606SStefano Zampini           if (!idxs_copied) {
61109162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
61119162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6112674ae819SStefano Zampini           }
6113674ae819SStefano Zampini         }
61149162d606SStefano Zampini       }
61159162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
611645a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6117eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6118a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
61199162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
61209162d606SStefano Zampini 
61219162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6122a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
61239162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6124a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
61259162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6126a773dcb8SStefano Zampini         } else { /* perform SVD */
61279162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6128674ae819SStefano Zampini 
6129674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6130984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6131984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6132984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6133984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
6134984c4197SStefano Zampini                 from that computed using LAPACKgesvd
6135984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
6136984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
6137984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
6138674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
6139e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6140984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6141674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
6142674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
61439162d606SStefano 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));
6144674ae819SStefano Zampini             }
6145674ae819SStefano Zampini           }
6146e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
6147e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6148e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6149674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6150c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6151674ae819SStefano Zampini #else
6152c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6153674ae819SStefano Zampini #endif
6154674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6155984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6156984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6157674ae819SStefano Zampini           j = 0;
615887b3baaaSStefano Zampini           while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6159674ae819SStefano Zampini           total_counts = total_counts-j;
616045a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
6161e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
6162c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6163c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6164c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6165c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6166c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6167c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6168674ae819SStefano Zampini           if (j<temp_constraints) {
6169984c4197SStefano Zampini             PetscInt ii;
6170984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6171674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
61729162d606SStefano 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));
6173674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6174984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
6175674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
61769162d606SStefano 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];
6177674ae819SStefano Zampini               }
6178674ae819SStefano Zampini             }
6179674ae819SStefano Zampini           }
6180674ae819SStefano Zampini #else  /* on missing GESVD */
6181e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6182e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6183b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6184674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6185674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
61869162d606SStefano 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));
6187674ae819SStefano Zampini #else
61889162d606SStefano 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));
6189674ae819SStefano Zampini #endif
6190984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6191674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6192984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6193e310c8b4SStefano Zampini           k = temp_constraints;
6194e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
6195674ae819SStefano Zampini           j = 0;
619687b3baaaSStefano Zampini           while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
619745a1bb75SStefano Zampini           valid_constraints = k-j;
6198911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
6199984c4197SStefano Zampini #endif /* on missing GESVD */
6200674ae819SStefano Zampini         }
6201a773dcb8SStefano Zampini       }
62029162d606SStefano Zampini       /* update pointers information */
62039162d606SStefano Zampini       if (valid_constraints) {
62049162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
62059162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
62069162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
62079162d606SStefano Zampini         /* set change_of_basis flag */
620845a1bb75SStefano Zampini         if (boolforchange) {
6209b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
62109162d606SStefano Zampini         }
6211b3d85658SStefano Zampini         total_counts_cc++;
621245a1bb75SStefano Zampini       }
621345a1bb75SStefano Zampini     }
6214984c4197SStefano Zampini     /* free workspace */
62158f1c130eSStefano Zampini     if (!skip_lapack) {
6216984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6217984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6218984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6219984c4197SStefano Zampini #endif
6220984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6221984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6222984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6223984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6224984c4197SStefano Zampini #endif
6225984c4197SStefano Zampini     }
6226984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6227984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6228984c4197SStefano Zampini     }
6229984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6230cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6231cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6232cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6233cf5a6209SStefano Zampini     }
6234cf5a6209SStefano Zampini     if (n_ISForFaces) {
6235cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6236cf5a6209SStefano Zampini     }
6237cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6238cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6239cf5a6209SStefano Zampini     }
6240cf5a6209SStefano Zampini     if (n_ISForEdges) {
6241cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6242cf5a6209SStefano Zampini     }
6243cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
624408122e43SStefano Zampini   } else {
624508122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6246984c4197SStefano Zampini 
624708122e43SStefano Zampini     total_counts = 0;
624808122e43SStefano Zampini     n_vertices = 0;
6249d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6250d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
625108122e43SStefano Zampini     }
625208122e43SStefano Zampini     max_constraints = 0;
62539162d606SStefano Zampini     total_counts_cc = 0;
625408122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
625508122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
62569162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
625708122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
625808122e43SStefano Zampini     }
62599162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
62609162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
62619162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
62629162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
626374d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
62649162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
62659162d606SStefano Zampini     total_counts_cc = 0;
62669162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
62679162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
62689162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
626908122e43SStefano Zampini       }
627008122e43SStefano Zampini     }
627108122e43SStefano Zampini 
62728bec7fa6SStefano Zampini     max_size_of_constraint = 0;
62739162d606SStefano 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]);
62749162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
627508122e43SStefano Zampini     /* Change of basis */
6276b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
627708122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
627808122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
627908122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6280b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
628108122e43SStefano Zampini         }
628208122e43SStefano Zampini       }
628308122e43SStefano Zampini     }
628408122e43SStefano Zampini   }
6285984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
62864f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
628708122e43SStefano Zampini 
62889162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
62899162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
62906080607fSStefano 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);
6291674ae819SStefano Zampini 
6292674ae819SStefano Zampini   /* Create constraint matrix */
6293674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
629416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6295984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6296984c4197SStefano Zampini 
6297984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6298a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
62995a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
630074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6301984c4197SStefano Zampini   total_primal_vertices=0;
6302b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
63039162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
63049162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
630572b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
63069162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6307b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
630864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
63099162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
63109162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6311a717540cSStefano Zampini       }
6312b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
631391af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6314a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6315a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6316a717540cSStefano Zampini       }
6317fa434743SStefano Zampini     } else {
6318b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6319fa434743SStefano Zampini     }
6320a717540cSStefano Zampini   }
6321b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6322b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6323674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
632470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
63254f1b2e48SStefano 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);
63260e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
63270e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6328984c4197SStefano Zampini 
6329984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
633074d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6331785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6332984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
633374d5cdf7SStefano Zampini 
6334984c4197SStefano Zampini   j = total_primal_vertices;
633574d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6336b3d85658SStefano Zampini   cum = total_primal_vertices;
63379162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
63384641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6339b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6340b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6341b3d85658SStefano Zampini       cum++;
63429162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
634374d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
634474d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
634574d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
634674d5cdf7SStefano Zampini       }
63479162d606SStefano Zampini       j += constraints_n[i];
6348674ae819SStefano Zampini     }
6349674ae819SStefano Zampini   }
6350674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6351e1b21442SStefano Zampini   ierr = MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6352674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6353088faed8SStefano Zampini 
6354674ae819SStefano Zampini   /* set values in constraint matrix */
6355984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
63560e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6357674ae819SStefano Zampini   }
6358984c4197SStefano Zampini   total_counts = total_primal_vertices;
63599162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
63604641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
63619162d606SStefano Zampini       PetscInt *cols;
63629162d606SStefano Zampini 
63639162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
63649162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
63659162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
63669162d606SStefano Zampini         PetscInt    row = total_counts+k;
63679162d606SStefano Zampini         PetscScalar *vals;
63689162d606SStefano Zampini 
63699162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
63709162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
63719162d606SStefano Zampini       }
63729162d606SStefano Zampini       total_counts += constraints_n[i];
6373674ae819SStefano Zampini     }
6374674ae819SStefano Zampini   }
6375674ae819SStefano Zampini   /* assembling */
6376674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6377674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63783272d46bSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,NULL,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6379088faed8SStefano Zampini 
6380674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6381674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6382026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6383984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6384984c4197SStefano Zampini     /* working stuff for GEQRF */
63855a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6386984c4197SStefano Zampini     PetscBLASInt lqr_work;
6387984c4197SStefano Zampini     /* working stuff for UNGQR */
63885a52fde0SStefano Zampini     PetscScalar  *gqr_work = NULL,lgqr_work_t;
6389984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6390984c4197SStefano Zampini     /* working stuff for TRTRS */
63915a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
63923f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6393984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6394984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6395984c4197SStefano Zampini     PetscScalar  *start_vals;
6396984c4197SStefano Zampini     /* working stuff for values insertion */
63974641a718SStefano Zampini     PetscBT      is_primal;
639864efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6399906d46d4SStefano Zampini     /* matrix sizes */
6400906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6401906d46d4SStefano Zampini     /* temporary change of basis */
6402906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6403cf5a6209SStefano Zampini     /* extra space for debugging */
64045a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6405984c4197SStefano Zampini 
6406906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6407906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
640816f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6409bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6410906d46d4SStefano Zampini     /* nonzeros for local mat */
6411bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
64121dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6413bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
64141dd7afcfSStefano Zampini     } else {
64151dd7afcfSStefano Zampini       const PetscInt *ii;
64161dd7afcfSStefano Zampini       PetscInt       n;
64171dd7afcfSStefano Zampini       PetscBool      flg_row;
64181dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
64191dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
64201dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
64211dd7afcfSStefano Zampini     }
64229162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6423a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
64249162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6425a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
64269162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6427a717540cSStefano Zampini         } else {
64289162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
64299162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6430a717540cSStefano Zampini         }
6431a717540cSStefano Zampini       }
6432a717540cSStefano Zampini     }
6433906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6434e1b21442SStefano Zampini     ierr = MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6435bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
64361dd7afcfSStefano Zampini     /* Set interior change in the matrix */
64371dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6438bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6439906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6440a717540cSStefano Zampini       }
64411dd7afcfSStefano Zampini     } else {
64421dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
64431dd7afcfSStefano Zampini       PetscScalar    *aa;
64441dd7afcfSStefano Zampini       PetscInt       n;
64451dd7afcfSStefano Zampini       PetscBool      flg_row;
64461dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
64471dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
64481dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
64491dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
64501dd7afcfSStefano Zampini       }
64511dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
64521dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
64531dd7afcfSStefano Zampini     }
6454a717540cSStefano Zampini 
6455a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6456a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6457a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6458a717540cSStefano Zampini     }
6459a717540cSStefano Zampini 
6460a717540cSStefano Zampini 
6461a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6462a717540cSStefano Zampini     /*
6463a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6464a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6465a717540cSStefano Zampini 
6466a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6467a717540cSStefano Zampini 
6468a6b551f4SStefano 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)
6469a6b551f4SStefano Zampini 
6470a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6471a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6472a717540cSStefano Zampini             |              ...                        |
6473a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6474a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6475a717540cSStefano Zampini 
6476a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6477a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6478a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6479a6b551f4SStefano Zampini 
6480a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6481a717540cSStefano Zampini     */
64825a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6483984c4197SStefano Zampini       /* space to store Q */
6484854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
64854e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
64864e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6487984c4197SStefano Zampini       /* first we issue queries for optimal work */
64883f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64893f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
64903f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6491984c4197SStefano Zampini       lqr_work = -1;
64923f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6493984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6494984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6495785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6496984c4197SStefano Zampini       lgqr_work = -1;
64973f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64983f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
64993f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
65003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
65013f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6502c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6503c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6504984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6505785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6506984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6507785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6508a717540cSStefano Zampini       /* allocating workspace for check */
6509a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6510cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6511a717540cSStefano Zampini       }
6512a717540cSStefano Zampini     }
6513984c4197SStefano Zampini     /* array to store whether a node is primal or not */
65144641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6515473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
65160e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
65176080607fSStefano 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);
651839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
651939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
652039e2fb2aSStefano Zampini     }
652139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6522984c4197SStefano Zampini 
6523a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
65249162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
65259162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
65264641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6527984c4197SStefano Zampini         /* get constraint info */
65289162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6529984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6530984c4197SStefano Zampini 
6531984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
65326080607fSStefano 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);
6533674ae819SStefano Zampini         }
6534984c4197SStefano Zampini 
6535fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6536a717540cSStefano Zampini 
6537a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6538a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
65399162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6540a717540cSStefano Zampini           }
6541984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
65429162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6543984c4197SStefano Zampini 
6544984c4197SStefano Zampini           /* compute QR decomposition of constraints */
65453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
65463f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
65473f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6548674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
65493f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6550984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6551674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6552984c4197SStefano Zampini 
6553984c4197SStefano Zampini           /* explictly compute R^-T */
6554984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6555984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
65563f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
65573f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
65583f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
65593f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6560984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
65613f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6562984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6563984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6564984c4197SStefano Zampini 
6565a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
65663f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
65673f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
65683f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
65693f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6570984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6571c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6572c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6573984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6574984c4197SStefano Zampini 
6575984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6576984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6577984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
65783f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
65793f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
65803f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
65813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
65823f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
65833f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6584984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
65859162d606SStefano 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));
6586984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
65879162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6588984c4197SStefano Zampini 
6589984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
65909162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6591984c4197SStefano Zampini           /* insert cols for primal dofs */
6592984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6593984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
65949162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6595906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6596984c4197SStefano Zampini           }
6597984c4197SStefano Zampini           /* insert cols for dual dofs */
6598984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
65999162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6600984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
66019162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6602906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6603984c4197SStefano Zampini               j++;
6604674ae819SStefano Zampini             }
6605674ae819SStefano Zampini           }
6606984c4197SStefano Zampini 
6607984c4197SStefano Zampini           /* check change of basis */
6608984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6609984c4197SStefano Zampini             PetscInt   ii,jj;
6610984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6611c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6612c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6613c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6614c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6615c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6616c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6617984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6618cf5a6209SStefano 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));
6619984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6620984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6621984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6622cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6623c068d9bbSLisandro 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;
6624674ae819SStefano Zampini               }
6625674ae819SStefano Zampini             }
6626984c4197SStefano Zampini             if (!valid_qr) {
662722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6628984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6629984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6630cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
66316080607fSStefano 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);
6632674ae819SStefano Zampini                   }
6633c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
66346080607fSStefano 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);
6635984c4197SStefano Zampini                   }
6636984c4197SStefano Zampini                 }
6637984c4197SStefano Zampini               }
6638674ae819SStefano Zampini             } else {
663922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6640674ae819SStefano Zampini             }
6641674ae819SStefano Zampini           }
6642a717540cSStefano Zampini         } else { /* simple transformation block */
6643a717540cSStefano Zampini           PetscInt    row,col;
6644a6b551f4SStefano Zampini           PetscScalar val,norm;
6645a6b551f4SStefano Zampini 
6646a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
66479162d606SStefano 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));
6648a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
66499162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
66509162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6651bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
66529162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6653906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
66549162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6655a717540cSStefano Zampini             } else {
6656a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
66579162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6658a717540cSStefano Zampini                 if (row != col) {
66599162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6660a717540cSStefano Zampini                 } else {
66619162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6662a717540cSStefano Zampini                 }
6663906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6664a717540cSStefano Zampini               }
6665a717540cSStefano Zampini             }
6666a717540cSStefano Zampini           }
666798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
666822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6669a717540cSStefano Zampini           }
6670674ae819SStefano Zampini         }
6671984c4197SStefano Zampini       } else {
6672984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
66736080607fSStefano 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);
6674674ae819SStefano Zampini         }
6675674ae819SStefano Zampini       }
6676674ae819SStefano Zampini     }
6677a717540cSStefano Zampini 
6678a717540cSStefano Zampini     /* free workspace */
6679a717540cSStefano Zampini     if (qr_needed) {
6680984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6681cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6682984c4197SStefano Zampini       }
6683984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6684984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6685984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6686984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6687984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6688674ae819SStefano Zampini     }
6689a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6690906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6691906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6692906d46d4SStefano Zampini 
6693906d46d4SStefano Zampini     /* assembling of global change of variable */
669488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6695bbb9e6c6SStefano Zampini       Mat      tmat;
669616f15bc4SStefano Zampini       PetscInt bs;
669716f15bc4SStefano Zampini 
6698906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6699906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6700bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6701bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6702487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6703487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6704bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6705bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
670616f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
670716f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6708906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6709bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6710487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6711bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6712bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6713bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6714e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6715e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6716bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6717bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
671888c03ad3SStefano Zampini 
6719906d46d4SStefano Zampini       /* check */
6720906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6721906d46d4SStefano Zampini         PetscReal error;
6722906d46d4SStefano Zampini         Vec       x,x_change;
6723906d46d4SStefano Zampini 
6724906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6725906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6726906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6727906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6728e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6729e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6730bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6731e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6732e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6733906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6734906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6735906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6736637e8532SStefano Zampini         if (error > PETSC_SMALL) {
67376080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
6738637e8532SStefano Zampini         }
6739906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6740906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6741906d46d4SStefano Zampini       }
6742b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6743b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6744b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6745bf3a8328SStefano Zampini 
674613903a91SSatish 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");
6747b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6748ac632422SStefano Zampini           Mat                    S_new,tmat;
6749bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6750bbb9e6c6SStefano Zampini 
6751bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
67527dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6753bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6754bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6755bf3a8328SStefano Zampini             IS                     is_V;
6756b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6757b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6758b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6759b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6760b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6761bf3a8328SStefano Zampini           }
6762bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6763ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6764b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6765ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6766bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6767bf3a8328SStefano Zampini             const PetscScalar *array;
6768bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6769bf3a8328SStefano Zampini             PetscInt          i,n_V;
6770bf3a8328SStefano Zampini 
6771b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6772b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6773b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6774b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6775b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6776b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6777b087196eSStefano Zampini               PetscScalar val;
6778b087196eSStefano Zampini               PetscInt    idx;
6779b087196eSStefano Zampini 
6780b087196eSStefano Zampini               idx = idxs_V[i];
6781b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6782b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6783b087196eSStefano Zampini             }
6784b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6785b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6786bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6787bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6788bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6789bf3a8328SStefano Zampini           }
6790ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6791ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6792ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6793ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6794b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6795ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6796bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6797b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6798bf3a8328SStefano Zampini             }
6799ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6800ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6801ac632422SStefano Zampini           }
6802b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
680388c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6804b96c3477SStefano Zampini         }
6805c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6806b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6807c9db6a07SStefano Zampini           PetscInt i;
6808c9db6a07SStefano Zampini 
6809c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6810c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6811c9db6a07SStefano Zampini           }
6812c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6813c9db6a07SStefano Zampini         }
6814b96c3477SStefano Zampini       }
681516909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
681616909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
681716909a7fSStefano Zampini       } else {
6818906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
681916909a7fSStefano Zampini       }
68201dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
682127b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
682272b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
682372b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
682472b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
682572b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
682672b8c272SStefano Zampini     }
68271dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
682827b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6829b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6830b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6831906d46d4SStefano Zampini     } else {
68321dd7afcfSStefano Zampini       Mat benign_global = NULL;
683327b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
68341dd7afcfSStefano Zampini         Mat M;
68351dd7afcfSStefano Zampini 
68369e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
68379e9b7b1fSStefano Zampini         ierr = VecCopy(matis->counter,pcis->vec1_N);CHKERRQ(ierr);
68389e9b7b1fSStefano Zampini         ierr = VecReciprocal(pcis->vec1_N);CHKERRQ(ierr);
68399e9b7b1fSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global);CHKERRQ(ierr);
68409e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
68411dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
68421dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
6843906d46d4SStefano Zampini         } else {
68449e9b7b1fSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M);CHKERRQ(ierr);
68459e9b7b1fSStefano Zampini           ierr = MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES);CHKERRQ(ierr);
6846906d46d4SStefano Zampini         }
68479e9b7b1fSStefano Zampini         ierr = MatISSetLocalMat(benign_global,M);CHKERRQ(ierr);
68489e9b7b1fSStefano Zampini         ierr = MatDestroy(&M);CHKERRQ(ierr);
68499e9b7b1fSStefano Zampini         ierr = MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68509e9b7b1fSStefano Zampini         ierr = MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68511dd7afcfSStefano Zampini       }
68521dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
68531dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
68541dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
685527b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
68561dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
68571dd7afcfSStefano Zampini       }
68581dd7afcfSStefano Zampini     }
685916909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
686016909a7fSStefano Zampini       IS             is_global;
686116909a7fSStefano Zampini       const PetscInt *gidxs;
686216909a7fSStefano Zampini 
686316909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
686416909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
686516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
68667dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
686716909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
686816909a7fSStefano Zampini     }
68691dd7afcfSStefano Zampini   }
68701dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
68711dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6872b9b85e73SStefano Zampini   }
6873a717540cSStefano Zampini 
687472b8c272SStefano Zampini   if (!pcbddc->fake_change) {
68754f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
68764f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
68774f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
68784f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6879019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6880019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6881019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6882019a44ceSStefano Zampini     }
6883019a44ceSStefano Zampini 
6884019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6885727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6886727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
68879f47a83aSStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6888c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
68890e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
68909f47a83aSStefano Zampini         ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6891727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6892727cdba6SStefano Zampini       }
68930e6343abSStefano Zampini     }
6894727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6895b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
689672b8c272SStefano Zampini   }
689772b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6898727cdba6SStefano Zampini 
6899a717540cSStefano Zampini   /* flush dbg viewer */
6900b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6901b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6902b8ffe317SStefano Zampini   }
6903a717540cSStefano Zampini 
6904e310c8b4SStefano Zampini   /* free workspace */
6905a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
69064641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
690708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
69089162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
69099162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
691008122e43SStefano Zampini   } else {
69119162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
69129162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
69139162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
691408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
691508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
69169162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
69179162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
691808122e43SStefano Zampini   }
6919674ae819SStefano Zampini   PetscFunctionReturn(0);
6920674ae819SStefano Zampini }
692104a6f24aSStefano Zampini /* #undef PETSC_MISSING_LAPACK_GESVD */
6922674ae819SStefano Zampini 
6923674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6924674ae819SStefano Zampini {
692571582508SStefano Zampini   ISLocalToGlobalMapping map;
6926674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6927674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
692866da6bd7Sstefano_zampini   PetscInt               i,N;
692966da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
693066da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6931674ae819SStefano Zampini 
6932674ae819SStefano Zampini   PetscFunctionBegin;
69338af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6934b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
69358e61c736SStefano Zampini     /* Reset previously computed graph */
69368e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6937674ae819SStefano Zampini     /* Init local Graph struct */
69387fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
693971582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6940be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6941674ae819SStefano Zampini 
69427a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
69437a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
69447a0e7b2cSstefano_zampini     }
6945575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
69466080607fSStefano 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);
69479577ea80SStefano Zampini 
6948674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
694966da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
69504d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
69514d379d7bSStefano Zampini       PetscInt  nvtxs;
6952e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6953674ae819SStefano Zampini 
69542fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
69552fffb893SStefano Zampini       if (flg_row) {
69564d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6957b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
69582fffb893SStefano Zampini       }
69592fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
696066da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6961674ae819SStefano Zampini     }
69629b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
69639b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6964674ae819SStefano Zampini     }
6965674ae819SStefano Zampini 
6966ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
6967ab8c8b98SStefano Zampini       PetscReal    *lcoords;
6968ab8c8b98SStefano Zampini       PetscInt     n;
6969ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
6970ab8c8b98SStefano Zampini 
6971ab8c8b98SStefano 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);
6972ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
6973ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
6974ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
6975ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
6976ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6977ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6978ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
6979ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
6980ab8c8b98SStefano Zampini 
6981ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
6982ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
6983ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
6984ab8c8b98SStefano Zampini     }
6985ab8c8b98SStefano 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);
69861c7a958bSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && !pcbddc->corner_selected);
6987ab8c8b98SStefano Zampini 
6988674ae819SStefano Zampini     /* Setup of Graph */
69894b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
699014f95afaSStefano 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);
6991674ae819SStefano Zampini 
69924f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
69934f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
69944f1b2e48SStefano Zampini       PetscInt *local_subs;
69954f1b2e48SStefano Zampini 
69964f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
69974f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
69984f1b2e48SStefano Zampini         const PetscInt *idxs;
69994f1b2e48SStefano Zampini         PetscInt       nl,j;
70004f1b2e48SStefano Zampini 
70014f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
70024f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
700371582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
70044f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
70054f1b2e48SStefano Zampini       }
70064f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
70074f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
70084f1b2e48SStefano Zampini     }
70098af8fcf9SStefano Zampini   }
70104f1b2e48SStefano Zampini 
7011cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7012674ae819SStefano Zampini     /* Graph's connected components analysis */
7013674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
701471582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
70158af8fcf9SStefano Zampini   }
701666da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7017674ae819SStefano Zampini   PetscFunctionReturn(0);
7018674ae819SStefano Zampini }
7019674ae819SStefano Zampini 
70209a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
70219a7d3425SStefano Zampini {
70229a7d3425SStefano Zampini   PetscInt       i,j;
70239a7d3425SStefano Zampini   PetscScalar    *alphas;
70249a7d3425SStefano Zampini   PetscErrorCode ierr;
70259a7d3425SStefano Zampini 
70269a7d3425SStefano Zampini   PetscFunctionBegin;
70278c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
7028785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
70298c0031efSStefano Zampini   ierr = VecNormalize(vecs[0],NULL);CHKERRQ(ierr);
70308c0031efSStefano Zampini   for (i=1;i<n;i++) {
70318c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
70328c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
70338c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
70349a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
70359a7d3425SStefano Zampini   }
70369a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
70379a7d3425SStefano Zampini   PetscFunctionReturn(0);
70389a7d3425SStefano Zampini }
70399a7d3425SStefano Zampini 
7040bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7041e7931f94SStefano Zampini {
704257de7509SStefano Zampini   Mat            A;
7043e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
7044e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
704552e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
704652e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7047bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
704857de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
704927b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
705027b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
705127b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
705227b6a85dSStefano Zampini   MPI_Comm       subcomm;
705352e5ac9dSStefano Zampini   PetscErrorCode ierr;
7054a57a6d2fSStefano Zampini 
7055e7931f94SStefano Zampini   PetscFunctionBegin;
705657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
705757de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7058fbfcfee5SBarry 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);
705957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
706057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
70616080607fSStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %D",*n_subdomains);
706257de7509SStefano Zampini 
706357de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
706457de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
706557de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
706657de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
706757de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
7068bb360cb4SStefano Zampini   im_active = !!n;
706957de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
707057de7509SStefano Zampini   void_procs = size - active_procs;
707157de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
707257de7509SStefano Zampini   if (void_procs) {
707357de7509SStefano Zampini     PetscInt ncand;
707457de7509SStefano Zampini 
707557de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
707657de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
707757de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
707857de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
707957de7509SStefano Zampini       if (!procs_candidates[i]) {
708057de7509SStefano Zampini         procs_candidates[ncand++] = i;
708157de7509SStefano Zampini       }
708257de7509SStefano Zampini     }
708357de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
708457de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
708557de7509SStefano Zampini   }
708657de7509SStefano Zampini 
7087bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
708814f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
7089bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7090bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
709114f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
709214f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
709314f0bfb9SStefano Zampini     else dest = rank;
709457de7509SStefano Zampini     if (im_active) {
709557de7509SStefano Zampini       issize = 1;
709657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
709714f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
709857de7509SStefano Zampini       } else {
709914f0bfb9SStefano Zampini         isidx = dest;
710057de7509SStefano Zampini       }
710157de7509SStefano Zampini     } else {
710257de7509SStefano Zampini       issize = 0;
710357de7509SStefano Zampini       isidx = -1;
710457de7509SStefano Zampini     }
7105bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
710657de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7107daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
710857de7509SStefano Zampini     PetscFunctionReturn(0);
710957de7509SStefano Zampini   }
7110c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7111c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
711227b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7113e7931f94SStefano Zampini 
7114e7931f94SStefano Zampini   /* Get info on mapping */
71153bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7116e7931f94SStefano Zampini 
7117e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7118785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7119e7931f94SStefano Zampini   xadj[0] = 0;
7120e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7121785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7122785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7123bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
712427b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
712527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
712627b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7127e7931f94SStefano Zampini 
712827b6a85dSStefano Zampini   xadj_count = 0;
71292b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
713027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
713127b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7132d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7133d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7134d023bfaeSStefano Zampini         xadj_count++;
713527b6a85dSStefano Zampini         break;
713627b6a85dSStefano Zampini       }
7137e7931f94SStefano Zampini     }
7138e7931f94SStefano Zampini   }
7139d023bfaeSStefano Zampini   xadj[1] = xadj_count;
714027b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
71413bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7142e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7143e7931f94SStefano Zampini 
71443837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7145e7931f94SStefano Zampini 
714627b6a85dSStefano Zampini   /* Restrict work on active processes only */
714727b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
714827b6a85dSStefano Zampini   if (void_procs) {
714927b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
715027b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
715127b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
715227b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
715327b6a85dSStefano Zampini   } else {
715427b6a85dSStefano Zampini     psubcomm = NULL;
715527b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
715627b6a85dSStefano Zampini   }
715727b6a85dSStefano Zampini 
715827b6a85dSStefano Zampini   v_wgt = NULL;
715927b6a85dSStefano Zampini   if (!color) {
7160e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7161e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7162e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7163c8587f34SStefano Zampini   } else {
716452e5ac9dSStefano Zampini     Mat             subdomain_adj;
716552e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
716652e5ac9dSStefano Zampini     MatPartitioning partitioner;
716727b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
716852e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
716957de7509SStefano Zampini     PetscMPIInt     size;
7170b0c7d250SStefano Zampini     PetscBool       aggregate;
7171b0c7d250SStefano Zampini 
717227b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
717327b6a85dSStefano Zampini     if (void_procs) {
717427b6a85dSStefano Zampini       PetscInt prank = rank;
7175785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
717627b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
7177e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7178e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7179c8587f34SStefano Zampini       }
7180e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
718127b6a85dSStefano Zampini     } else {
718227b6a85dSStefano Zampini       oldranks = NULL;
718327b6a85dSStefano Zampini     }
7184b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
718527b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7186b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7187b0c7d250SStefano Zampini       PetscMPIInt nrank;
7188b0c7d250SStefano Zampini       PetscScalar *vals;
7189b0c7d250SStefano Zampini 
719027b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7191b0c7d250SStefano Zampini       lrows = 0;
7192b0c7d250SStefano Zampini       if (nrank<redprocs) {
7193b0c7d250SStefano Zampini         lrows = size/redprocs;
7194b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7195b0c7d250SStefano Zampini       }
719627b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7197b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7198b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7199b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7200b0c7d250SStefano Zampini       row = nrank;
7201b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7202b0c7d250SStefano Zampini       cols = adjncy;
7203b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7204b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7205b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7206b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7207b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
720852e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
720952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
721052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7211b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
721227b6a85dSStefano Zampini       if (use_vwgt) {
721327b6a85dSStefano Zampini         Vec               v;
721427b6a85dSStefano Zampini         const PetscScalar *array;
721527b6a85dSStefano Zampini         PetscInt          nl;
721627b6a85dSStefano Zampini 
721727b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7218bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
721927b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
722027b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
722127b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
722227b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
722327b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
722422db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
722527b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
722627b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
722727b6a85dSStefano Zampini       }
7228b0c7d250SStefano Zampini     } else {
722927b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
723027b6a85dSStefano Zampini       if (use_vwgt) {
723127b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7232bb360cb4SStefano Zampini         v_wgt[0] = n;
723327b6a85dSStefano Zampini       }
7234b0c7d250SStefano Zampini     }
723522b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7236e7931f94SStefano Zampini 
7237e7931f94SStefano Zampini     /* Partition */
723827b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7239e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
724027b6a85dSStefano Zampini     if (v_wgt) {
7241e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7242c8587f34SStefano Zampini     }
724357de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
724457de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7245e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7246e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
724722b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7248e7931f94SStefano Zampini 
724952e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
72506583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
725152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
725252e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
725357de7509SStefano Zampini     if (!aggregate) {
725457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
725527b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
725627b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
725727b6a85dSStefano Zampini #endif
725857de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
725927b6a85dSStefano Zampini       } else if (oldranks) {
7260b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
726127b6a85dSStefano Zampini       } else {
726227b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
726357de7509SStefano Zampini       }
726428143c3dSStefano Zampini     } else {
72657fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7266b0c7d250SStefano Zampini       PetscMPIInt tag;
7267b0c7d250SStefano Zampini       MPI_Request *reqs;
7268b0c7d250SStefano Zampini 
7269b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7270b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7271b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
727227b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
727328143c3dSStefano Zampini       }
72747fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7275b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7276b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
727757de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
727827b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
727927b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
728027b6a85dSStefano Zampini #endif
72817fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
728227b6a85dSStefano Zampini       } else if (oldranks) {
72837fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
728427b6a85dSStefano Zampini       } else {
72857fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7286e7931f94SStefano Zampini       }
728757de7509SStefano Zampini     }
728852e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7289e7931f94SStefano Zampini     /* clean up */
7290e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
729152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7292e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7293e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7294e7931f94SStefano Zampini   }
729527b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
729657de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7297e7931f94SStefano Zampini 
7298e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7299e7931f94SStefano Zampini   i = 1;
730027b6a85dSStefano Zampini   if (!color) i=0;
730157de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7302e7931f94SStefano Zampini   PetscFunctionReturn(0);
7303e7931f94SStefano Zampini }
7304e7931f94SStefano Zampini 
7305e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7306e7931f94SStefano Zampini 
73071e0482f5SStefano 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[])
7308e7931f94SStefano Zampini {
730970cf5478SStefano Zampini   Mat                    local_mat;
7310e7931f94SStefano Zampini   IS                     is_sends_internal;
73119d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
73121ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
73139d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7314e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7315e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7316e7931f94SStefano Zampini   const PetscInt*        is_indices;
7317e7931f94SStefano Zampini   MatType                new_local_type;
7318e7931f94SStefano Zampini   /* buffers */
7319e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
732028143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
73219d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
7322e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
73231ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7324e7931f94SStefano Zampini   /* MPI */
732528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
732628143c3dSStefano Zampini   PetscSubcomm           subcomm;
7327e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
732828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
732928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
73301ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
73311ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
73321ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7333e7931f94SStefano Zampini   PetscErrorCode         ierr;
7334e7931f94SStefano Zampini 
7335e7931f94SStefano Zampini   PetscFunctionBegin;
733657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7337e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7338fbfcfee5SBarry 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);
733957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
734057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
734157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
734257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
734357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
73441ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
73451ae86dd6SStefano Zampini   if (nvecs) {
73461ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
73471ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
73481ae86dd6SStefano Zampini   }
734957de7509SStefano Zampini   /* further checks */
7350e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7351e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7352e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7353e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7354e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
735557de7509SStefano Zampini   if (reuse && *mat_n) {
735670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
735757de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
735870cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
735928143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
736070cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
736170cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
736270cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
736370cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
736470cf5478SStefano Zampini   }
7365e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7366e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
736757de7509SStefano Zampini 
7368e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7369e7931f94SStefano Zampini   if (!is_sends) {
737028143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7371bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7372c8587f34SStefano Zampini   } else {
7373e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7374e7931f94SStefano Zampini     is_sends_internal = is_sends;
7375c8587f34SStefano Zampini   }
7376e7931f94SStefano Zampini 
7377e7931f94SStefano Zampini   /* get comm */
7378a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7379e7931f94SStefano Zampini 
7380e7931f94SStefano Zampini   /* compute number of sends */
7381e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7382e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7383e7931f94SStefano Zampini 
7384e7931f94SStefano Zampini   /* compute number of receives */
7385e569e4e1SStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
7386e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&iflags);CHKERRQ(ierr);
7387e569e4e1SStefano Zampini   ierr = PetscMemzero(iflags,size*sizeof(*iflags));CHKERRQ(ierr);
7388e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7389e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7390e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7391e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7392e7931f94SStefano Zampini 
739328143c3dSStefano Zampini   /* restrict comm if requested */
739428143c3dSStefano Zampini   subcomm = 0;
739528143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
739628143c3dSStefano Zampini   if (restrict_comm) {
7397779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7398779c1cceSStefano Zampini 
739928143c3dSStefano Zampini     color = 0;
740053a05cb3SStefano Zampini     if (restrict_full) {
740153a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
740253a05cb3SStefano Zampini     } else {
740353a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
740453a05cb3SStefano Zampini     }
7405b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
7406e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
740728143c3dSStefano Zampini     /* check if reuse has been requested */
740857de7509SStefano Zampini     if (reuse) {
740928143c3dSStefano Zampini       if (*mat_n) {
741028143c3dSStefano Zampini         PetscMPIInt subcommsize2;
741128143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
741228143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
741328143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
741428143c3dSStefano Zampini       } else {
741528143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
741628143c3dSStefano Zampini       }
741728143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7418779c1cceSStefano Zampini       PetscMPIInt rank;
7419779c1cceSStefano Zampini 
7420779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
742128143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
742228143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
742328143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7424306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
742528143c3dSStefano Zampini     }
742628143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
742728143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
742828143c3dSStefano Zampini   } else {
742928143c3dSStefano Zampini     comm_n = comm;
743028143c3dSStefano Zampini   }
743128143c3dSStefano Zampini 
7432e7931f94SStefano Zampini   /* prepare send/receive buffers */
7433e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_idxs);CHKERRQ(ierr);
7434e569e4e1SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,size*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7435e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_vals);CHKERRQ(ierr);
7436e569e4e1SStefano Zampini   ierr = PetscMemzero(ilengths_vals,size*sizeof(*ilengths_vals));CHKERRQ(ierr);
743728143c3dSStefano Zampini   if (nis) {
7438e569e4e1SStefano Zampini     ierr = PetscCalloc1(size,&ilengths_idxs_is);CHKERRQ(ierr);
743928143c3dSStefano Zampini   }
7440e7931f94SStefano Zampini 
744128143c3dSStefano Zampini   /* Get data from local matrices */
74426c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7443e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7444e7931f94SStefano Zampini     /*
7445e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7446e7931f94SStefano Zampini        send_buffer_idxs should contain:
7447e7931f94SStefano Zampini        - MatType_PRIVATE type
7448e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7449e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7450e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7451e7931f94SStefano Zampini     */
74526c4ed002SBarry Smith   else {
7453e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
74543bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7455854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7456e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7457e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
74583bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7459e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
74603bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7461e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7462e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7463e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7464e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7465c8587f34SStefano Zampini     }
7466c8587f34SStefano Zampini   }
7467e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
746828143c3dSStefano Zampini   /* additional is (if any) */
746928143c3dSStefano Zampini   if (nis) {
747028143c3dSStefano Zampini     PetscMPIInt psum;
747128143c3dSStefano Zampini     PetscInt j;
747228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
747328143c3dSStefano Zampini       PetscInt plen;
747428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
747528143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
747628143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
747728143c3dSStefano Zampini     }
7478854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
747928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
748028143c3dSStefano Zampini       PetscInt plen;
748128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
748228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
748328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
748428143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
748528143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
748628143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
748728143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
748828143c3dSStefano Zampini     }
748928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
749028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
749128143c3dSStefano Zampini     }
749228143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
749328143c3dSStefano Zampini   }
74943b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
749528143c3dSStefano Zampini 
7496e7931f94SStefano Zampini   buf_size_idxs = 0;
7497e7931f94SStefano Zampini   buf_size_vals = 0;
749828143c3dSStefano Zampini   buf_size_idxs_is = 0;
74991ae86dd6SStefano Zampini   buf_size_vecs = 0;
7500e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7501e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7502e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
750328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
75041ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7505e7931f94SStefano Zampini   }
7506785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7507785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
750895ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
75091ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7510e7931f94SStefano Zampini 
7511e7931f94SStefano Zampini   /* get new tags for clean communications */
7512e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7513e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
751428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
75151ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7516e7931f94SStefano Zampini 
7517e7931f94SStefano Zampini   /* allocate for requests */
7518785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7519785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
752095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
75211ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7522785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7523785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
752495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
75251ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7526e7931f94SStefano Zampini 
7527e7931f94SStefano Zampini   /* communications */
7528e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7529e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
753028143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
75311ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7532e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7533e7931f94SStefano Zampini     source_dest = onodes[i];
7534e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7535e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7536e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7537e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
753828143c3dSStefano Zampini     if (nis) {
753957de7509SStefano Zampini       source_dest = onodes_is[i];
754028143c3dSStefano 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);
754128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
754228143c3dSStefano Zampini     }
75431ae86dd6SStefano Zampini     if (nvecs) {
75441ae86dd6SStefano Zampini       source_dest = onodes[i];
75451ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
75461ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
75471ae86dd6SStefano Zampini     }
7548e7931f94SStefano Zampini   }
7549e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7550e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7551e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7552e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
755328143c3dSStefano Zampini     if (nis) {
755428143c3dSStefano 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);
755528143c3dSStefano Zampini     }
75561ae86dd6SStefano Zampini     if (nvecs) {
75571ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
75581ae86dd6SStefano 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);
75591ae86dd6SStefano Zampini     }
7560e7931f94SStefano Zampini   }
7561e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7562e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7563e7931f94SStefano Zampini 
7564e7931f94SStefano Zampini   /* assemble new l2g map */
7565e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7566e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
75679d30be91SStefano Zampini   new_local_rows = 0;
7568e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
75699d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7570e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7571e7931f94SStefano Zampini   }
75729d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7573e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
75749d30be91SStefano Zampini   new_local_rows = 0;
7575e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
75769d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
75779d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7578e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7579e7931f94SStefano Zampini   }
75809d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
75819d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7582e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7583e7931f94SStefano Zampini 
7584e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7585e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7586e7931f94SStefano 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) */
7587e7931f94SStefano Zampini   if (n_recvs) {
758828143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7589e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7590e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7591e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7592e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7593e7931f94SStefano Zampini         break;
7594e7931f94SStefano Zampini       }
7595e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7596e7931f94SStefano Zampini     }
7597e7931f94SStefano Zampini     switch (new_local_type_private) {
759828143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7599e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7600e7931f94SStefano Zampini         bs = 1;
7601e7931f94SStefano Zampini         break;
7602e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7603e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7604e7931f94SStefano Zampini         bs = 1;
7605e7931f94SStefano Zampini         break;
7606e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7607e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7608e7931f94SStefano Zampini         break;
7609e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7610e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7611e7931f94SStefano Zampini         break;
7612e7931f94SStefano Zampini       default:
7613fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7614e7931f94SStefano Zampini         break;
7615e7931f94SStefano Zampini     }
7616ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7617ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
761828143c3dSStefano Zampini     bs = 1;
7619e7931f94SStefano Zampini   }
7620e7931f94SStefano Zampini 
762170cf5478SStefano Zampini   /* create MATIS object if needed */
762257de7509SStefano Zampini   if (!reuse) {
7623e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7624e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
762570cf5478SStefano Zampini   } else {
762670cf5478SStefano Zampini     /* it also destroys the local matrices */
762757de7509SStefano Zampini     if (*mat_n) {
762870cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
762957de7509SStefano Zampini     } else { /* this is a fake object */
763057de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
763157de7509SStefano Zampini     }
763270cf5478SStefano Zampini   }
763370cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7634e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
76359d30be91SStefano Zampini 
76369d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
76379d30be91SStefano Zampini 
76389d30be91SStefano Zampini   /* Global to local map of received indices */
76399d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
76409d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
76419d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
76429d30be91SStefano Zampini 
76439d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
76449d30be91SStefano Zampini   buf_size_idxs = 0;
76459d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
76469d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
76479d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
76489d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
76499d30be91SStefano Zampini   }
76509d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
76519d30be91SStefano Zampini 
76529d30be91SStefano Zampini   /* set preallocation */
76539d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
76549d30be91SStefano Zampini   if (!newisdense) {
76559d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
76569d30be91SStefano Zampini 
76579d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
76589d30be91SStefano Zampini     if (n_recvs) {
76599d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
76609d30be91SStefano Zampini     }
76619d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
76629d30be91SStefano Zampini       PetscInt j;
76639d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
76649d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
76659d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
76669d30be91SStefano Zampini         }
76679d30be91SStefano Zampini       } else {
76689d30be91SStefano Zampini         /* TODO */
76699d30be91SStefano Zampini       }
76709d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
76719d30be91SStefano Zampini     }
76729d30be91SStefano Zampini     if (new_local_nnz) {
76739d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
76749d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
76759d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
76769d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76779d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
76789d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76799d30be91SStefano Zampini     } else {
76809d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76819d30be91SStefano Zampini     }
76829d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
76839d30be91SStefano Zampini   } else {
76849d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76859d30be91SStefano Zampini   }
7686e7931f94SStefano Zampini 
7687e7931f94SStefano Zampini   /* set values */
7688e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
76899d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7690e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7691e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7692e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
76939d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7694e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7695e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7696e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
769728143c3dSStefano Zampini     } else {
769828143c3dSStefano Zampini       /* TODO */
7699e7931f94SStefano Zampini     }
7700e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7701e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7702e7931f94SStefano Zampini   }
7703e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7704e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
77053b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
770670cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
770770cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
77089d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7709e7931f94SStefano Zampini 
7710dfd14d43SStefano Zampini #if 0
771128143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7712e7931f94SStefano Zampini     Vec       lvec,rvec;
7713e7931f94SStefano Zampini     PetscReal infty_error;
7714e7931f94SStefano Zampini 
77152a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7716e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7717e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7718e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
771970cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7720e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7721e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7722e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7723e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7724e7931f94SStefano Zampini   }
772528143c3dSStefano Zampini #endif
7726e7931f94SStefano Zampini 
772728143c3dSStefano Zampini   /* assemble new additional is (if any) */
772828143c3dSStefano Zampini   if (nis) {
772928143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
773028143c3dSStefano Zampini 
773128143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7732854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
773328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
773428143c3dSStefano Zampini     psum = 0;
773528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
773628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
773728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
773828143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
773928143c3dSStefano Zampini         psum += plen;
774028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
774128143c3dSStefano Zampini       }
774228143c3dSStefano Zampini     }
7743854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7744854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
774528143c3dSStefano Zampini     for (i=1;i<nis;i++) {
774628143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
774728143c3dSStefano Zampini     }
774828143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
774928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
775028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
775128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
775228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
775328143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
775428143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
775528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
775628143c3dSStefano Zampini       }
775728143c3dSStefano Zampini     }
775828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
775928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
776028143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
776128143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
776228143c3dSStefano Zampini     }
776328143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
776428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
776528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
776628143c3dSStefano Zampini   }
7767e7931f94SStefano Zampini   /* free workspace */
776828143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7769e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7770e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7771e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7772e7931f94SStefano Zampini   if (isdense) {
7773e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7774e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
77753b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7776e7931f94SStefano Zampini   } else {
7777e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7778e7931f94SStefano Zampini   }
777928143c3dSStefano Zampini   if (nis) {
778028143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
778128143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
778228143c3dSStefano Zampini   }
77831ae86dd6SStefano Zampini 
77841ae86dd6SStefano Zampini   if (nvecs) {
77851ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77861ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77871ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77881ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
77891ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
77901ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
77911ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
77921ae86dd6SStefano Zampini     /* set values */
77931ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
77941ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
77951ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77961ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
77971ae86dd6SStefano Zampini       PetscInt j;
77981ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
77991ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
78001ae86dd6SStefano Zampini       }
78011ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
78021ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
78031ae86dd6SStefano Zampini     }
78041ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
78051ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
78061ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
78071ae86dd6SStefano Zampini   }
78081ae86dd6SStefano Zampini 
78091ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
78101ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7811e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7812e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
78131ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
781428143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7815e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7816e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
78171ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
781828143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7819e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7820e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7821e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7822e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7823e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
782428143c3dSStefano Zampini   if (nis) {
782528143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
782628143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
782728143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
782828143c3dSStefano Zampini   }
782928143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
783028143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
783128143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
783228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
783328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
783428143c3dSStefano Zampini     }
78351ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
78361ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
78371ae86dd6SStefano Zampini     }
783853a05cb3SStefano Zampini     *mat_n = NULL;
783928143c3dSStefano Zampini   }
7840e7931f94SStefano Zampini   PetscFunctionReturn(0);
7841e7931f94SStefano Zampini }
7842a57a6d2fSStefano Zampini 
784312edc857SStefano Zampini /* temporary hack into ksp private data structure */
7844af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
784512edc857SStefano Zampini 
7846c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7847c8587f34SStefano Zampini {
7848c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7849c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
785020a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
78511ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
78521e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
78539881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
785420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
78556e683305SStefano Zampini   IS                     coarse_is,*isarray;
78566e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
785730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7858e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
7859f9eb5b7dSStefano Zampini   PC                     pc_temp;
7860c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7861c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7862f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
78637274672aSStefano Zampini   PetscBool              coarse_reuse;
78641e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
786568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
786622bc73bbSStefano Zampini   PetscScalar            *array;
786757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
786857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
7869e569e4e1SStefano Zampini   PetscMPIInt            size;
78709881197aSStefano Zampini   PetscErrorCode         ierr;
7871fdc09c96SStefano Zampini 
7872c8587f34SStefano Zampini   PetscFunctionBegin;
787343371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
7874c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
787568457ee5SStefano 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 */
7876fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
78775a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
78787de4f681Sstefano_zampini 
78797de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7880fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7881f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7882f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7883f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7884fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
788551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
788651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7887727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7888fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7889fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7890fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7891f4ddd8eeSStefano Zampini       }
7892fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7893fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7894f4ddd8eeSStefano Zampini     }
789570cf5478SStefano Zampini     /* reset any subassembling information */
789657de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
789770cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
789857de7509SStefano Zampini     }
78996e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7900fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7901f4ddd8eeSStefano Zampini   }
790257de7509SStefano Zampini   /* assemble coarse matrix */
790357de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
790457de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
790557de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
790657de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
790718a45a71SStefano Zampini   } else {
790857de7509SStefano Zampini     coarse_mat = NULL;
790957de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
79106e683305SStefano Zampini   }
7911e7931f94SStefano Zampini 
7912abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7913abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7914abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7915abbbba34SStefano Zampini 
7916abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
791722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
791822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
791922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
792022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7921e176bc59SStefano 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);
79226e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
79236e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79246e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7925abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7926abbbba34SStefano Zampini 
792757de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
792857de7509SStefano Zampini   im_active = !!(pcis->n);
792957de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
793057de7509SStefano Zampini 
793114f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
793257de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
793357de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
7934e569e4e1SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
793557de7509SStefano Zampini   coarse_mat_is        = NULL;
793657de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
793757de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
7938e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
793957de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
7940e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
794157de7509SStefano Zampini   if (multilevel_requested) {
794257de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
794357de7509SStefano Zampini     restr      = PETSC_FALSE;
794457de7509SStefano Zampini     full_restr = PETSC_FALSE;
794557de7509SStefano Zampini   } else {
7946e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
794757de7509SStefano Zampini     restr      = PETSC_TRUE;
794857de7509SStefano Zampini     full_restr = PETSC_TRUE;
794957de7509SStefano Zampini   }
7950e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
795157de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
795257de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7953a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7954bb360cb4SStefano Zampini       if (multilevel_requested) {
7955bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7956bb360cb4SStefano Zampini       } else {
7957bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7958bb360cb4SStefano Zampini       }
7959a198735bSStefano Zampini     } else {
79607de4f681Sstefano_zampini       PetscMPIInt rank;
7961a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
7962e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
7963a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7964a198735bSStefano Zampini     }
796557de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
796657de7509SStefano Zampini     PetscInt    psum;
796757de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
796857de7509SStefano Zampini     else psum = 0;
796957de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7970*075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
797157de7509SStefano Zampini   }
797257de7509SStefano Zampini   /* determine if we can go multilevel */
797357de7509SStefano Zampini   if (multilevel_requested) {
797457de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
797557de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
797657de7509SStefano Zampini   }
797757de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
797857de7509SStefano Zampini 
7979e4d548c7SStefano Zampini   /* dump subassembling pattern */
7980e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7981e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7982e4d548c7SStefano Zampini   }
79836e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
79841e0482f5SStefano Zampini   nedcfield = -1;
79851e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
79866e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
79876e683305SStefano Zampini     const PetscInt         *idxs;
79886e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
79896e683305SStefano Zampini 
79906e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
79910be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
79926e683305SStefano Zampini     /* allocate space for temporary storage */
7993854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7994854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
79956e683305SStefano Zampini     /* allocate for IS array */
79966e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
79971e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
79981e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
79991e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
80001e0482f5SStefano Zampini       } else {
80011e0482f5SStefano Zampini         nedcfield = 0;
80026080607fSStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%D)",nisdofs);
80031e0482f5SStefano Zampini         nisdofs = 1;
80041e0482f5SStefano Zampini       }
80051e0482f5SStefano Zampini     }
80066e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
800727b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
800830368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
8009854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
80106e683305SStefano Zampini     /* dofs splitting */
80116e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
80126e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
80131e0482f5SStefano Zampini       if (nedcfield != i) {
80146e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
80156e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
80166e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
80176e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
80181e0482f5SStefano Zampini       } else {
80191e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
80201e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
80211e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
80226080607fSStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %D != %D",tsize,nout);
80231e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
80241e0482f5SStefano Zampini       }
80256e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
802630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
80276e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
80286e683305SStefano Zampini     }
80296e683305SStefano Zampini     /* neumann boundaries */
80306e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
80316e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
80326e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
80336e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
80346e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
80356e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
80366e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
803730368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
80386e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
80396e683305SStefano Zampini     }
80406e683305SStefano Zampini     /* free memory */
80416e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
80426e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
80436e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
80446e683305SStefano Zampini   } else {
80456e683305SStefano Zampini     nis = 0;
80466e683305SStefano Zampini     nisdofs = 0;
80476e683305SStefano Zampini     nisneu = 0;
804830368db7SStefano Zampini     nisvert = 0;
80496e683305SStefano Zampini     isarray = NULL;
80506e683305SStefano Zampini   }
80516e683305SStefano Zampini   /* destroy no longer needed map */
80526e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
80536e683305SStefano Zampini 
805457de7509SStefano Zampini   /* subassemble */
805557de7509SStefano Zampini   if (multilevel_allowed) {
80561ae86dd6SStefano Zampini     Vec       vp[1];
80571ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
805857de7509SStefano Zampini     PetscBool reuse,reuser;
80591ae86dd6SStefano Zampini 
806057de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
806157de7509SStefano Zampini     else reuse = PETSC_FALSE;
806257de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
80631ae86dd6SStefano Zampini     vp[0] = NULL;
80641ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
80651ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
80661ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
80671ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
80681ae86dd6SStefano Zampini       nvecs = 1;
80691ae86dd6SStefano Zampini 
80701ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8071a198735bSStefano Zampini         Mat      B,loc_divudotp;
80721ae86dd6SStefano Zampini         Vec      v,p;
80731ae86dd6SStefano Zampini         IS       dummy;
80741ae86dd6SStefano Zampini         PetscInt np;
80751ae86dd6SStefano Zampini 
8076a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8077a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
80781ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
80797dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
80801ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
80811ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
80821ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
80831ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
80841ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
80851ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
80861ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
80871ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
80881ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
80891ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
80901ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
80911ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
809274e2c79eSStefano Zampini       }
80931ae86dd6SStefano Zampini     }
80941ae86dd6SStefano Zampini     if (reuser) {
80951e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
809674e2c79eSStefano Zampini     } else {
80971e0482f5SStefano 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);
80981ae86dd6SStefano Zampini     }
80991ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
81001ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
81011ae86dd6SStefano Zampini       PetscInt    nl;
81021ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
81031ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
81041ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
81051ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
81061ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
81071ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
81081ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
81091ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8110a198735bSStefano Zampini     } else {
8111a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
81121ae86dd6SStefano Zampini     }
81131ae86dd6SStefano Zampini   } else {
81141e0482f5SStefano 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);
81156e683305SStefano Zampini   }
811657de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
811757de7509SStefano Zampini     if (!multilevel_allowed) {
8118487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
81196e683305SStefano Zampini     } else {
812057de7509SStefano Zampini       Mat A;
8121779c1cceSStefano Zampini 
812257de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
812357de7509SStefano Zampini       if (coarse_mat_is) {
812457de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
812557de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
812657de7509SStefano Zampini         coarse_mat = coarse_mat_is;
812757de7509SStefano Zampini       }
812857de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
812957de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
813057de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
8131779c1cceSStefano Zampini     }
8132779c1cceSStefano Zampini   }
813357de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
813457de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
81356e683305SStefano Zampini 
81366e683305SStefano Zampini   /* create local to global scatters for coarse problem */
813768457ee5SStefano Zampini   if (compute_vecs) {
81386e683305SStefano Zampini     PetscInt lrows;
81396e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
814057de7509SStefano Zampini     if (coarse_mat) {
814157de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
81426e683305SStefano Zampini     } else {
81436e683305SStefano Zampini       lrows = 0;
81446e683305SStefano Zampini     }
81456e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
81466e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
814789535278SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD);CHKERRQ(ierr);
81486e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
814935928de7SBarry Smith     ierr = VecScatterCreateWithData(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
81506e683305SStefano Zampini   }
81516e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8152c8587f34SStefano Zampini 
8153f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8154f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8155f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8156f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8157f9eb5b7dSStefano Zampini   } else {
8158f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8159f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8160c8587f34SStefano Zampini   }
8161c8587f34SStefano Zampini 
81626e683305SStefano Zampini   /* print some info if requested */
81636e683305SStefano Zampini   if (pcbddc->dbg_flag) {
81646e683305SStefano Zampini     if (!multilevel_allowed) {
81656e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
81666e683305SStefano Zampini       if (multilevel_requested) {
81676080607fSStefano 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);
81686e683305SStefano Zampini       } else if (pcbddc->max_levels) {
81696080607fSStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%D)\n",pcbddc->max_levels);CHKERRQ(ierr);
81706e683305SStefano Zampini       }
81716e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
81726e683305SStefano Zampini     }
81736e683305SStefano Zampini   }
81746e683305SStefano Zampini 
81751e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
81761e0482f5SStefano Zampini   coarseG = NULL;
81771e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
81781e0482f5SStefano Zampini     MPI_Comm ccomm;
81791e0482f5SStefano Zampini     if (coarse_mat) {
81801e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
81811e0482f5SStefano Zampini     } else {
81821e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
81831e0482f5SStefano Zampini     }
81841e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
81851e0482f5SStefano Zampini   }
81861e0482f5SStefano Zampini 
8187f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
818857de7509SStefano Zampini   if (coarse_mat) {
81897274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
81906a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
81917274672aSStefano Zampini 
81926e683305SStefano Zampini     if (pcbddc->dbg_flag) {
819357de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
81946e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
81956e683305SStefano Zampini     }
8196f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8197312be037SStefano Zampini       char   prefix[256],str_level[16];
8198e604994aSStefano Zampini       size_t len;
81991e0482f5SStefano Zampini 
820057de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8201422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8202c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8203f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
820457de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8205c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
82066e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8207c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
82081e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8209c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8210e604994aSStefano Zampini       /* prefix */
8211e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8212e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8213e604994aSStefano Zampini       if (!pcbddc->current_level) {
8214a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8215a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8216c8587f34SStefano Zampini       } else {
8217e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8218312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8219312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8220a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
822134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
822235529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8223a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8224e604994aSStefano Zampini       }
8225e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
82263e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
82273e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
82283e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
82293e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8230f9eb5b7dSStefano Zampini       /* allow user customization */
8231f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
8232e569e4e1SStefano Zampini       /* get some info after set from options */
8233e569e4e1SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
8234e569e4e1SStefano Zampini       /* multilevel cannot be done with coarse PCs different from BDDC or NN */
8235e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8236e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
8237e569e4e1SStefano Zampini       if (multilevel_allowed && !isbddc && !isnn) {
8238e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
8239e569e4e1SStefano Zampini         ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8240e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
8241e569e4e1SStefano Zampini         ierr   = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
8242e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8243e569e4e1SStefano Zampini       }
82443e3c6dadSStefano Zampini     }
82453e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
824651bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
82473e3c6dadSStefano Zampini     if (nisdofs) {
82483e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
82493e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
82503e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
82513e3c6dadSStefano Zampini       }
82523e3c6dadSStefano Zampini     }
82533e3c6dadSStefano Zampini     if (nisneu) {
82543e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
82553e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8256312be037SStefano Zampini     }
825730368db7SStefano Zampini     if (nisvert) {
825830368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
825930368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
826030368db7SStefano Zampini     }
82611e0482f5SStefano Zampini     if (coarseG) {
82621e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
82631e0482f5SStefano Zampini     }
8264f9eb5b7dSStefano Zampini 
8265f9eb5b7dSStefano Zampini     /* get some info after set from options */
8266f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8267b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8268b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8269f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8270f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
8271f9eb5b7dSStefano Zampini     }
8272b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
82737274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
82747274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
8275b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8276b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
8277b76f3995Sstefano_zampini     }
82787274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
82794f3a063dSStefano Zampini     if (isredundant) {
82804f3a063dSStefano Zampini       KSP inner_ksp;
82814f3a063dSStefano Zampini       PC  inner_pc;
82829326c5c6Sstefano_zampini 
82834f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
82844f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
82854f3a063dSStefano Zampini     }
8286f9eb5b7dSStefano Zampini 
828757de7509SStefano Zampini     /* parameters which miss an API */
82887274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
828957de7509SStefano Zampini     if (isbddc) {
8290720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
82917274672aSStefano Zampini 
8292720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
829357de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8294e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
829527b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
829627b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8297a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8298a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8299a198735bSStefano Zampini         IS                     row,col;
8300a198735bSStefano Zampini         const PetscInt         *gidxs;
8301a198735bSStefano Zampini         PetscInt               n,st,M,N;
8302a198735bSStefano Zampini 
8303a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8304a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8305a198735bSStefano Zampini         st   = st-n;
8306a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8307a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8308a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8309a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8310a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8311a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8312a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8313a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8314a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8315a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8316a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8317a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8318a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8319a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8320a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8321a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8322a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8323a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8324a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8325a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
83268ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8327a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8328720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8329bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8330720d30f9SStefano Zampini       }
8331d4d8cf7bSStefano Zampini     }
83329881197aSStefano Zampini 
83333301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
83345a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
83353301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
83363301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
83373301b35fSStefano Zampini     }
83383301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
83393301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
83403301b35fSStefano Zampini     }
83413301b35fSStefano Zampini     if (pc->pmat->spd_set) {
83423301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
83433301b35fSStefano Zampini     }
834427b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
834527b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
834627b6a85dSStefano Zampini     }
83476e683305SStefano Zampini     /* set operators */
834804fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
83493007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix);CHKERRQ(ierr);
83505f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
83516e683305SStefano Zampini     if (pcbddc->dbg_flag) {
83526e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
83536e683305SStefano Zampini     }
83546e683305SStefano Zampini   }
83551e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
83566e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8357b1ecc7b1SStefano Zampini #if 0
8358b9b85e73SStefano Zampini   {
8359b9b85e73SStefano Zampini     PetscViewer viewer;
8360b9b85e73SStefano Zampini     char filename[256];
8361b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8362b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
83636a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8364b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8365f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8366b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8367b9b85e73SStefano Zampini   }
8368b9b85e73SStefano Zampini #endif
8369f9eb5b7dSStefano Zampini 
837098a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
837198a51de6SStefano Zampini     Vec crhs,csol;
837204708bb6SStefano Zampini 
8373f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8374f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8375f347579bSStefano Zampini     if (!csol) {
83762a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8377f9eb5b7dSStefano Zampini     }
8378f347579bSStefano Zampini     if (!crhs) {
83792a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8380f347579bSStefano Zampini     }
8381b0f5fe93SStefano Zampini   }
83821ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8383b0f5fe93SStefano Zampini 
8384b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8385b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8386b0f5fe93SStefano Zampini 
8387b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
83884f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
83894f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
83904f1b2e48SStefano Zampini     }
8391b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8392b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8393b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8394b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8395b0f5fe93SStefano Zampini     if (coarse_mat) {
8396b0f5fe93SStefano Zampini       Vec         nullv;
8397b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8398b0f5fe93SStefano Zampini       PetscInt    nl;
8399b0f5fe93SStefano Zampini 
8400b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8401b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8402b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8403b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8404b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8405b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8406b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8407b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8408b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8409b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8410b0f5fe93SStefano Zampini     }
8411b0f5fe93SStefano Zampini   }
841243371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8413b0f5fe93SStefano Zampini 
841443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8415b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8416b0f5fe93SStefano Zampini     PetscBool ispreonly;
8417b0f5fe93SStefano Zampini 
8418b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8419b0f5fe93SStefano Zampini       PetscBool isnull;
8420b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8421bef83e63SStefano Zampini       if (isnull) {
8422b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8423b0f5fe93SStefano Zampini       }
8424bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8425b0f5fe93SStefano Zampini     }
8426b0f5fe93SStefano Zampini     /* setup coarse ksp */
8427b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8428cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8429cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
84306e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8431c8587f34SStefano Zampini       KSP       check_ksp;
84322b510759SStefano Zampini       KSPType   check_ksp_type;
8433c8587f34SStefano Zampini       PC        check_pc;
84346e683305SStefano Zampini       Vec       check_vec,coarse_vec;
84356a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
84362b510759SStefano Zampini       PetscInt  its;
84376e683305SStefano Zampini       PetscBool compute_eigs;
84386e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
84396e683305SStefano Zampini       PetscInt  neigs;
84408e185a42SStefano Zampini       const char *prefix;
8441c8587f34SStefano Zampini 
84422b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
84436e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
844415579a77SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0);CHKERRQ(ierr);
8445399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
844623ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8447f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8448e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8449e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8450e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
84512b510759SStefano Zampini       if (ispreonly) {
84522b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
84536e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
84542b510759SStefano Zampini       } else {
8455cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
84566e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8457c8587f34SStefano Zampini       }
8458c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
84596e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
84606e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
84616e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8462a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8463a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8464a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8465a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8466c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8467c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8468c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8469c8587f34SStefano Zampini       /* create random vec */
84702701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8471c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
84726e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8473c8587f34SStefano Zampini       /* solve coarse problem */
84746e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8475cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
84766e683305SStefano Zampini       if (compute_eigs) {
8477854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8478854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
84796e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
84801ae86dd6SStefano Zampini         if (neigs) {
84816e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
84826e683305SStefano Zampini           lambda_min = eigs_r[0];
84836e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
84842701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
84852701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8486cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8487cbcc2c2aSStefano Zampini             }
8488c8587f34SStefano Zampini           }
8489c8587f34SStefano Zampini         }
84901ae86dd6SStefano Zampini       }
8491cbcc2c2aSStefano Zampini 
8492c8587f34SStefano Zampini       /* check coarse problem residual error */
84936e683305SStefano Zampini       if (pcbddc->dbg_flag) {
84946e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
84956e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
84966e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8497c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
84986e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
84996e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8500779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
85016e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
85026e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
85036e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
85046e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8505b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8506b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8507b0f5fe93SStefano Zampini         }
85086e683305SStefano Zampini         if (compute_eigs) {
85096e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8510b03ebc13SStefano Zampini           KSPConvergedReason reason;
8511deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8512c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8513b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
85146e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8515b03ebc13SStefano 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);
85166e683305SStefano Zampini           for (i=0;i<neigs;i++) {
85176e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8518c8587f34SStefano Zampini           }
85196e683305SStefano Zampini         }
85206e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
85216e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
85226e683305SStefano Zampini       }
8523e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
85242701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8525c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
85266e683305SStefano Zampini       if (compute_eigs) {
85276e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
85286e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8529c8587f34SStefano Zampini       }
85306e683305SStefano Zampini     }
85316e683305SStefano Zampini   }
8532bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8533cbcc2c2aSStefano Zampini   /* print additional info */
8534cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
85356e683305SStefano Zampini     /* waits until all processes reaches this point */
85366e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
85376080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %D\n",pcbddc->current_level);CHKERRQ(ierr);
8538cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8539cbcc2c2aSStefano Zampini   }
8540cbcc2c2aSStefano Zampini 
85412b510759SStefano Zampini   /* free memory */
8542fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
854343371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8544c8587f34SStefano Zampini   PetscFunctionReturn(0);
8545c8587f34SStefano Zampini }
8546674ae819SStefano Zampini 
8547f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8548f34684f1SStefano Zampini {
8549f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8550f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8551f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8552dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8553dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
855473be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8555dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8556f34684f1SStefano Zampini   PetscErrorCode ierr;
8557f34684f1SStefano Zampini 
8558f34684f1SStefano Zampini   PetscFunctionBegin;
8559f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
85606c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8561dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
85623bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8563dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8564dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
85656583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8566dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8567dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8568dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
85696c4ed002SBarry 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);
8570dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8571dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8572dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8573dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8574dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8575f34684f1SStefano Zampini 
8576f34684f1SStefano Zampini   /* check numbering */
8577f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8578019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8579dc456d91SStefano Zampini     PetscInt    i;
8580b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8581f34684f1SStefano Zampini 
8582f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8583f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8584f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
85851575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8586019a44ceSStefano Zampini     /* counter */
8587019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8588019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8589019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8590019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8591019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8592019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8593f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8594f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8595727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8596f34684f1SStefano Zampini     }
8597f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8598f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8599f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8600e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8601e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8602e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8603e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8604f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8605019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8606f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8607019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
86082c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
860975c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8610b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
86112c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
86126080607fSStefano 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);
8613f34684f1SStefano Zampini       }
8614f34684f1SStefano Zampini     }
8615019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8616b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8617f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8618f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8619f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8620f34684f1SStefano Zampini     }
8621f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8622f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8623e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8624e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8625f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
86266080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %D (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8627b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8628ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8629ca8b9ea9SStefano Zampini 
8630ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
86313bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8632f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8633f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8634f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8635f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
86366080607fSStefano 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);
8637f34684f1SStefano Zampini       }
8638f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8639ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8640f34684f1SStefano Zampini     }
8641f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
86421575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8643302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8644f34684f1SStefano Zampini   }
86456080607fSStefano Zampini 
8646f34684f1SStefano Zampini   /* get back data */
8647f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8648f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8649674ae819SStefano Zampini   PetscFunctionReturn(0);
8650674ae819SStefano Zampini }
8651674ae819SStefano Zampini 
8652a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8653e456f2a8SStefano Zampini {
8654e456f2a8SStefano Zampini   IS             localis_t;
8655a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8656e456f2a8SStefano Zampini   PetscScalar    *vals;
8657e456f2a8SStefano Zampini   PetscErrorCode ierr;
8658e456f2a8SStefano Zampini 
8659e456f2a8SStefano Zampini   PetscFunctionBegin;
8660a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8661e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8662854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8663e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8664e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8665a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8666a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
86671035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
86683151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8669a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
86701035eff8SStefano Zampini   }
8671a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8672e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8673e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8674a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8675a7dc3881SStefano Zampini   /* now compute set in local ordering */
8676a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8677a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8678a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8679a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8680a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8681ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8682e456f2a8SStefano Zampini       lsize++;
8683e456f2a8SStefano Zampini     }
8684e456f2a8SStefano Zampini   }
8685854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8686a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8687ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8688e456f2a8SStefano Zampini       idxs[lsize++] = i;
8689e456f2a8SStefano Zampini     }
8690e456f2a8SStefano Zampini   }
8691a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8692a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8693e456f2a8SStefano Zampini   *localis = localis_t;
8694e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8695e456f2a8SStefano Zampini }
8696906d46d4SStefano Zampini 
869708122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8698b96c3477SStefano Zampini {
8699a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8700b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8701b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8702a64f4aa4SStefano Zampini   Mat                 S_j;
8703b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8704b96c3477SStefano Zampini   PetscBool           free_used_adj;
8705b96c3477SStefano Zampini   PetscErrorCode      ierr;
8706b96c3477SStefano Zampini 
8707b96c3477SStefano Zampini   PetscFunctionBegin;
870843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8709b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8710b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
871108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8712b96c3477SStefano Zampini     used_xadj = NULL;
8713b96c3477SStefano Zampini     used_adjncy = NULL;
8714b96c3477SStefano Zampini   } else {
871508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
871608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
871708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
871808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8719b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8720b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8721b96c3477SStefano Zampini     } else {
87222fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8723b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8724b96c3477SStefano Zampini       PetscInt       nvtxs;
8725b96c3477SStefano Zampini 
87262fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
87272fffb893SStefano Zampini       if (flg_row) {
8728b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8729b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8730b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8731b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
87322fffb893SStefano Zampini       } else {
87332fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
87342fffb893SStefano Zampini         used_xadj = NULL;
87352fffb893SStefano Zampini         used_adjncy = NULL;
87362fffb893SStefano Zampini       }
87372fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8738b96c3477SStefano Zampini     }
8739b96c3477SStefano Zampini   }
8740d5574798SStefano Zampini 
8741d5574798SStefano Zampini   /* setup sub_schurs data */
8742a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8743df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8744df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8745a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
874691af6908SStefano 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);
8747a64f4aa4SStefano Zampini   } else {
874872b8c272SStefano Zampini     Mat       change = NULL;
87499d54b7f4SStefano Zampini     Vec       scaling = NULL;
8750111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8751111315fdSstefano_zampini     PetscInt  benign_n;
8752111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8753111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8754111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8755a3df083aSStefano Zampini 
87565feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
87575feab87aSStefano Zampini       PetscInt n_vertices;
87585feab87aSStefano Zampini 
87595feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
87602034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
87615feab87aSStefano Zampini     }
876204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
876304708bb6SStefano Zampini     if (!isseqaij) {
876404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
876504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
876604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
876704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
876804708bb6SStefano Zampini       } else {
8769511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
877004708bb6SStefano Zampini       }
877104708bb6SStefano Zampini     }
8772a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8773a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8774ca92afb2SStefano Zampini     } else {
8775a3df083aSStefano Zampini       benign_n = 0;
8776ca92afb2SStefano Zampini     }
8777b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8778b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8779b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
878072b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
878122db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8782b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
878322db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8784b7ab4a40SStefano Zampini     }
8785b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8786b7ab4a40SStefano 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 */
8787b7ab4a40SStefano Zampini     if (need_change) {
878888c03ad3SStefano Zampini       PC_IS   *pcisf;
878988c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
879088c03ad3SStefano Zampini       PC      pcf;
879188c03ad3SStefano Zampini 
8792e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
879388c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
879488c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
879588c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8796b9be95fcSstefano_zampini 
879788c03ad3SStefano Zampini       /* hacks */
879888c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
879972b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
880072b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
880172b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
880272b8c272SStefano Zampini       pcisf->n                     = pcis->n;
880372b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
880488c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
880588c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
880688c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
880788c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
880888c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
880988c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
881072b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
881188c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8812b9be95fcSstefano_zampini 
8813b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
881488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
881572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
881672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
881772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
881872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8819b9be95fcSstefano_zampini 
882088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
882172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
882288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
882388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
882488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
882588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
882688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
882788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8828b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
882988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
883088c03ad3SStefano Zampini     }
88319d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8832111315fdSstefano_zampini 
8833111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8834111315fdSstefano_zampini     if (iP) {
8835111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8836111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8837111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8838111315fdSstefano_zampini     }
8839111315fdSstefano_zampini     if (discrete_harmonic) {
8840111315fdSstefano_zampini       Mat A;
8841111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8842111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8843111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8844111315fdSstefano_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);
8845111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8846111315fdSstefano_zampini     } else {
884791af6908SStefano 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);
8848111315fdSstefano_zampini     }
884972b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
885072b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8851ca92afb2SStefano Zampini   }
8852d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8853b96c3477SStefano Zampini 
8854b96c3477SStefano Zampini   /* free adjacency */
8855b96c3477SStefano Zampini   if (free_used_adj) {
8856b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8857b96c3477SStefano Zampini   }
885843371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8859b96c3477SStefano Zampini   PetscFunctionReturn(0);
8860b96c3477SStefano Zampini }
8861b96c3477SStefano Zampini 
886208122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8863b96c3477SStefano Zampini {
8864b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8865b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8866b96c3477SStefano Zampini   PCBDDCGraph         graph;
8867b96c3477SStefano Zampini   PetscErrorCode      ierr;
8868b96c3477SStefano Zampini 
8869b96c3477SStefano Zampini   PetscFunctionBegin;
8870b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
887108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
88723301b35fSStefano Zampini     IS       verticesIS,verticescomm;
88733301b35fSStefano Zampini     PetscInt vsize,*idxs;
8874b96c3477SStefano Zampini 
8875b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
88763301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
88773301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
88783301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
88793301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8880c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8881b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8882be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8883441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
88843301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8885b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8886b96c3477SStefano Zampini   } else {
8887b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8888b96c3477SStefano Zampini   }
8889e4d548c7SStefano Zampini   /* print some info */
88905c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8891e4d548c7SStefano Zampini     IS       vertices;
8892e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8893c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8894e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8895e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8896e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8897e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
88986080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,(int)nv,pcbddc->use_vertices);CHKERRQ(ierr);
88996080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,(int)nedges,pcbddc->use_edges);CHKERRQ(ierr);
89006080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,(int)nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8901e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8902e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8903c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8904e4d548c7SStefano Zampini   }
8905b96c3477SStefano Zampini 
8906b96c3477SStefano Zampini   /* sub_schurs init */
8907b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8908b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8909b334f244SStefano Zampini   }
891088113c35SStefano 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);
8911a64f4aa4SStefano Zampini 
8912b96c3477SStefano Zampini   /* free graph struct */
891308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8914b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8915b96c3477SStefano Zampini   }
8916b96c3477SStefano Zampini   PetscFunctionReturn(0);
8917b96c3477SStefano Zampini }
8918fa34dd3eSStefano Zampini 
8919fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8920fa34dd3eSStefano Zampini {
8921fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8922fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8923fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8924fa34dd3eSStefano Zampini 
8925fa34dd3eSStefano Zampini   PetscFunctionBegin;
8926fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8927fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
89284f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8929fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
89304f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
893175c01103SStefano Zampini     PetscReal      norm;
8932fa34dd3eSStefano Zampini     PetscInt       i;
8933fa34dd3eSStefano Zampini 
8934fa34dd3eSStefano Zampini     /* B0 and B0_B */
8935fa34dd3eSStefano Zampini     if (zerodiag) {
8936fa34dd3eSStefano Zampini       IS       dummy;
8937fa34dd3eSStefano Zampini 
89384f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
89397dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8940fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8941fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8942fa34dd3eSStefano Zampini     }
8943fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8944fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8945fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8946fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8947fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8948fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8949fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8950fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8951fa34dd3eSStefano Zampini     /* S_j */
8952fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8953fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8954fa34dd3eSStefano Zampini 
8955fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8956fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8957fa34dd3eSStefano Zampini     /* continuous in primal space */
8958fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8959fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8960fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8961fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
89624f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
89634f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8964fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8965fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8966fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8967fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8968fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8969fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8970fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8971fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8972fa34dd3eSStefano Zampini 
8973fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8974fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8975fa34dd3eSStefano Zampini     /* local with Schur */
8976fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8977fa34dd3eSStefano Zampini     if (zerodiag) {
8978fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
89794f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8980fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8981fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8982fa34dd3eSStefano Zampini     }
8983fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8984fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8985fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8986fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8987fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8988fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8989fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8990fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8991fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8992fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8993fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8994fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8995fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8996fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8997fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8998fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8999fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9000fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9001fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9002fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9003fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9004fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9005fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9006fa34dd3eSStefano Zampini     if (zerodiag) {
9007fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
9008fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
90094f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
9010fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9011fa34dd3eSStefano Zampini     }
9012fa34dd3eSStefano Zampini     /* BDDC */
9013fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
9014fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
9015fa34dd3eSStefano Zampini 
9016fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
9017fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
9018fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
90196080607fSStefano Zampini     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);CHKERRQ(ierr);
90204f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
90216080607fSStefano 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);
9022fa34dd3eSStefano Zampini     }
90234f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
9024fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
9025fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
9026fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
9027fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9028fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
9029fa34dd3eSStefano Zampini   }
9030fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9031fa34dd3eSStefano Zampini }
90321e0482f5SStefano Zampini 
90331e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
90341e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
90351e0482f5SStefano Zampini {
90361e0482f5SStefano Zampini   Mat            At;
90371e0482f5SStefano Zampini   IS             rows;
90381e0482f5SStefano Zampini   PetscInt       rst,ren;
90391e0482f5SStefano Zampini   PetscErrorCode ierr;
90401e0482f5SStefano Zampini   PetscLayout    rmap;
90411e0482f5SStefano Zampini 
90421e0482f5SStefano Zampini   PetscFunctionBegin;
90431e0482f5SStefano Zampini   rst = ren = 0;
90441e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
90451e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
90461e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
90471e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
90481e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
90491e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
90501e0482f5SStefano Zampini   }
9051e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
90527dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
90531e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
90541e0482f5SStefano Zampini 
90551e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
90561e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
90571e0482f5SStefano Zampini     IS         from,to;
90581e0482f5SStefano Zampini     Vec        gvec;
90591e0482f5SStefano Zampini     PetscInt   lsize;
90601e0482f5SStefano Zampini 
90611e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
90621e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
90631e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
90641e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
90651e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
90661e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
90671e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
90681e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
90691e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
90701e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
90711e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
90721e0482f5SStefano Zampini     b->A = a->A;
90731e0482f5SStefano Zampini     b->B = a->B;
90741e0482f5SStefano Zampini 
90751e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
90761e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
90771e0482f5SStefano Zampini     b->rowindices      = 0;
90781e0482f5SStefano Zampini     b->rowvalues       = 0;
90791e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
90801e0482f5SStefano Zampini 
90811e0482f5SStefano Zampini     (*B)->rmap         = rmap;
90821e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
90831e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
90841e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
90851e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
90861e0482f5SStefano Zampini 
90871e0482f5SStefano Zampini     if (a->colmap) {
90881e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
90891e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
90901e0482f5SStefano Zampini #else
90911e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
90921e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90931e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90941e0482f5SStefano Zampini #endif
90951e0482f5SStefano Zampini     } else b->colmap = 0;
90961e0482f5SStefano Zampini     if (a->garray) {
90971e0482f5SStefano Zampini       PetscInt len;
90981e0482f5SStefano Zampini       len  = a->B->cmap->n;
90991e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
91001e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
91011e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
91021e0482f5SStefano Zampini     } else b->garray = 0;
91031e0482f5SStefano Zampini 
91041e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
91051e0482f5SStefano Zampini     b->lvec = a->lvec;
91061e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
91071e0482f5SStefano Zampini 
91081e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
91091e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
91101e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
91111e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
91121e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
911335928de7SBarry Smith     ierr = VecScatterCreateWithData(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
91141e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
91151e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
91161e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
91171e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
91181e0482f5SStefano Zampini   }
91191e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
91201e0482f5SStefano Zampini   PetscFunctionReturn(0);
91211e0482f5SStefano Zampini }
9122