xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 399ffe994e22ec4bff4e8fa4a49a4a09b0883c0e)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h>
5c80a6c00SStefano Zampini #include <petscdmplex.h>
6674ae819SStefano Zampini #include <petscblaslapack.h>
7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h>
97620a527SStefano Zampini #include <petscdmda.h>
10674ae819SStefano Zampini 
111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
121e0482f5SStefano Zampini 
13f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
14f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
16a13144ffSStefano Zampini {
17a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
18a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
19a13144ffSStefano Zampini   PetscReal      *sing;
20a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
21a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
22a13144ffSStefano Zampini   PetscErrorCode ierr;
23a13144ffSStefano Zampini 
24a13144ffSStefano Zampini   PetscFunctionBegin;
25a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
26a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
27614dbb09SStefano Zampini #else
28a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
29a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
30a13144ffSStefano Zampini 
31a13144ffSStefano Zampini   /* workspace */
32a13144ffSStefano Zampini   if (!work) {
33a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
34f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
35a13144ffSStefano Zampini   } else {
36a13144ffSStefano Zampini     ulw   = lw;
37a13144ffSStefano Zampini     uwork = work;
38a13144ffSStefano Zampini   }
39a13144ffSStefano Zampini   n = PetscMin(nr,nc);
40a13144ffSStefano Zampini   if (!rwork) {
41a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
42a13144ffSStefano Zampini   } else {
43a13144ffSStefano Zampini     sing = rwork;
44a13144ffSStefano Zampini   }
45a13144ffSStefano Zampini 
46a13144ffSStefano Zampini   /* SVD */
47a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
55a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
56a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
57a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
58a13144ffSStefano Zampini   if (!rwork) {
59a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   if (!work) {
62a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
63a13144ffSStefano Zampini   }
64a13144ffSStefano Zampini   /* create B */
65f498cd09SStefano Zampini   if (!range) {
66a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
67a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
68a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
69f498cd09SStefano Zampini   } else {
70f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
71f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
72f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
73f498cd09SStefano Zampini   }
74a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
75a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
76614dbb09SStefano Zampini #endif
77614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
78a13144ffSStefano Zampini   PetscFunctionBegin;
79a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
80a13144ffSStefano Zampini #endif
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1237dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
156a13144ffSStefano Zampini {
157a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
158a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1590569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
160eee23b56SStefano Zampini   Vec                    tvec;
161a13144ffSStefano Zampini   PetscSF                sfv;
1621e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
163a13144ffSStefano Zampini   MPI_Comm               comm;
164c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
165c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1667d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
167a13144ffSStefano Zampini   PetscScalar            *vals,*work;
168a13144ffSStefano Zampini   PetscReal              *rwork;
169a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1701e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
171a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
172eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
173b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
174a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
175b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
176637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
177b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179b03ebc13SStefano Zampini #endif
180213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
181a13144ffSStefano Zampini   PetscErrorCode         ierr;
182a13144ffSStefano Zampini 
183a13144ffSStefano Zampini   PetscFunctionBegin;
184213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
185213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
186213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
187213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
188213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
189213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
190213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
191213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
192a13144ffSStefano Zampini   print      = PETSC_FALSE;
193213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
194a13144ffSStefano Zampini 
195213b8bfaSStefano Zampini   /* Command line customization */
196213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
201213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
202213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203213b8bfaSStefano Zampini 
204213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2051e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2061e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   if (!singular) {
209a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
210a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
211c2151214SStefano Zampini     for (i=0;i<n;i++) {
212a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
213a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
214a13144ffSStefano Zampini         break;
215a13144ffSStefano Zampini       }
216a13144ffSStefano Zampini     }
217a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
219a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
220213b8bfaSStefano Zampini   }
221a13144ffSStefano Zampini 
222213b8bfaSStefano Zampini   /* Get Nedelec field */
223213b8bfaSStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
224c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= pcbddc->n_ISForDofsLocal) SETERRQ2(comm,PETSC_ERR_USER,"Invalid field for Nedelec %d: number of fields is %d",field,pcbddc->n_ISForDofsLocal);
225213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
226c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
227c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
228c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
229213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
230213b8bfaSStefano Zampini     ne            = n;
231213b8bfaSStefano Zampini     nedfieldlocal = NULL;
232213b8bfaSStefano Zampini     global        = PETSC_TRUE;
233213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
234213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
235213b8bfaSStefano Zampini 
236213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
237213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
238213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
239213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
240213b8bfaSStefano Zampini       PetscInt nc;
241213b8bfaSStefano Zampini 
242213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
243213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
244213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
245213b8bfaSStefano Zampini     }
246213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
248213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
249213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
250213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
251213b8bfaSStefano Zampini   } else {
252213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
253213b8bfaSStefano Zampini   }
254213b8bfaSStefano Zampini 
255213b8bfaSStefano Zampini   /* Sanity checks */
256213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
257213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
258213b8bfaSStefano Zampini   if (order && ne%order) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %d it's not a multiple of the order %d",ne,order);
259213b8bfaSStefano Zampini 
260213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2611e0482f5SStefano Zampini   if (setprimal) {
262eee23b56SStefano Zampini     IS       enedfieldlocal;
263eee23b56SStefano Zampini     PetscInt *eidxs;
264eee23b56SStefano Zampini 
265eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
266eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
267213b8bfaSStefano Zampini     if (nedfieldlocal) {
268213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
269eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
270eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
271eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
272eee23b56SStefano Zampini         }
273eee23b56SStefano Zampini       }
274eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
275213b8bfaSStefano Zampini     } else {
276213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
277213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
278213b8bfaSStefano Zampini           eidxs[cum++] = i;
279213b8bfaSStefano Zampini         }
280213b8bfaSStefano Zampini       }
281213b8bfaSStefano Zampini     }
282213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
285eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
287eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2881e0482f5SStefano Zampini     PetscFunctionReturn(0);
2891e0482f5SStefano Zampini   }
290a13144ffSStefano Zampini 
291213b8bfaSStefano Zampini   /* Compute some l2g maps */
292213b8bfaSStefano Zampini   if (nedfieldlocal) {
293c2151214SStefano Zampini     IS is;
294c2151214SStefano Zampini 
295c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
296c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2981e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2991e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
3001e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
3011e0482f5SStefano Zampini     if (global) {
3021e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3031e0482f5SStefano Zampini       el2g = al2g;
3041e0482f5SStefano Zampini     } else {
3051e0482f5SStefano Zampini       IS gis;
3061e0482f5SStefano Zampini 
3071e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3081e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3091e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3101e0482f5SStefano Zampini     }
311c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
312c2151214SStefano Zampini   } else {
3131e0482f5SStefano Zampini     /* restore default */
3141e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3151e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3161e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3171e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3181e0482f5SStefano Zampini     el2g = al2g;
319c2151214SStefano Zampini     fl2g = NULL;
320c2151214SStefano Zampini   }
321a13144ffSStefano Zampini 
322213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
323c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
324c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
325c2151214SStefano Zampini   if (nedfieldlocal) {
326c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
328c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
329c2151214SStefano Zampini   } else {
330c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
331c2151214SStefano Zampini   }
332c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
334213b8bfaSStefano Zampini 
335213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
336213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
337213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     if (global) {
3391e0482f5SStefano Zampini       PetscInt rst;
3401e0482f5SStefano Zampini 
341c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
342c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
343c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
344c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
345c2151214SStefano Zampini         }
346c2151214SStefano Zampini       }
347a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
348c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3491e0482f5SStefano Zampini     } else {
3501e0482f5SStefano Zampini       PetscInt *tbz;
3511e0482f5SStefano Zampini 
3521e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3561e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3571e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3581e0482f5SStefano Zampini           tbz[cum++] = i;
3591e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3621e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3631e0482f5SStefano Zampini     }
364213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
365213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
366213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
367213b8bfaSStefano Zampini   }
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3727dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
378a13144ffSStefano Zampini 
379213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
380c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
387a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
388213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
389213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
390a13144ffSStefano Zampini 
3911e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
392213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
393a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
394213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
395a13144ffSStefano Zampini 
396213b8bfaSStefano Zampini   if (print) {
397213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
398213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
399213b8bfaSStefano Zampini   }
400213b8bfaSStefano Zampini 
401213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4020569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4030569b399SStefano Zampini 
404a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4054e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4064e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4107d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
411c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
412a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
413a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
414a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
415c2151214SStefano Zampini     IS is;
416c2151214SStefano Zampini 
417c2151214SStefano Zampini     if (fl2g) {
418c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
419c2151214SStefano Zampini     } else {
420c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
421c2151214SStefano Zampini     }
422c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
423c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
424a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
425a13144ffSStefano Zampini       if (idxs[i] >= 0) {
426a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4277d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
428a13144ffSStefano Zampini       }
429a13144ffSStefano Zampini     }
430c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
431c2151214SStefano Zampini     if (fl2g) {
432c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
433c2151214SStefano Zampini     }
434a13144ffSStefano Zampini   }
435a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
436c2151214SStefano Zampini     IS is;
437c2151214SStefano Zampini 
438c2151214SStefano Zampini     if (fl2g) {
439c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
440c2151214SStefano Zampini     } else {
441c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
442c2151214SStefano Zampini     }
443c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
444c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
445a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
446a13144ffSStefano Zampini       if (idxs[i] >= 0) {
447a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
448a13144ffSStefano Zampini       }
449a13144ffSStefano Zampini     }
450c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
451c2151214SStefano Zampini     if (fl2g) {
452c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
453a13144ffSStefano Zampini     }
454c2151214SStefano Zampini   }
455c2151214SStefano Zampini 
456213b8bfaSStefano Zampini   /* Count neighs per dof */
457b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
458b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini 
4607d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4617d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
46262b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
46362b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
464b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
46562b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
46662b0c6f7SStefano Zampini     }
46762b0c6f7SStefano Zampini   }
468637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
46962b0c6f7SStefano Zampini   if (!conforming) {
47062b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
47162b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
47262b0c6f7SStefano Zampini   }
4734e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
474dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
47562b0c6f7SStefano Zampini   cum  = 0;
476a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
477dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47862b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
479a13144ffSStefano Zampini       marks[cum++] = i;
480dec27d64SStefano Zampini       continue;
481dec27d64SStefano Zampini     }
482dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
48362b0c6f7SStefano Zampini     if (!conforming) {
48462b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
485a13144ffSStefano Zampini         marks[cum++] = i;
486a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
487a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
488a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
489a13144ffSStefano Zampini         }
49062b0c6f7SStefano Zampini       } else {
49162b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
49262b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
49362b0c6f7SStefano Zampini            - at most 2 endpoints
49462b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49562b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49662b0c6f7SStefano Zampini         */
49762b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49862b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49962b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
50062b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
50162b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
50262b0c6f7SStefano Zampini           if (nconn > order) ends++;
50362b0c6f7SStefano Zampini           else if (nconn == order) ints++;
50462b0c6f7SStefano Zampini           else undef++;
50562b0c6f7SStefano Zampini         }
50662b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50762b0c6f7SStefano Zampini           marks[cum++] = i;
50862b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
50962b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
51062b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini           }
51262b0c6f7SStefano Zampini         }
51362b0c6f7SStefano Zampini       }
514a13144ffSStefano Zampini     }
515dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
516dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
517dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
518dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
519a13144ffSStefano Zampini     }
520dec27d64SStefano Zampini   }
52162b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5234e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
52462b0c6f7SStefano Zampini   if (!conforming) {
52562b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52662b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
52762b0c6f7SStefano Zampini   }
5284e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
529637e8532SStefano Zampini 
530b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5314e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
532a13144ffSStefano Zampini   if (print) {
5334e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5344e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5354e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
536a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
537a13144ffSStefano Zampini   }
538a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
539dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
540a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
541637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5427d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
543b03ebc13SStefano Zampini     if (!order) { /* variable order */
544dec27d64SStefano Zampini       PetscReal vorder = 0.;
545dec27d64SStefano Zampini 
546dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
547dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
548dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
549dec27d64SStefano Zampini       ord  = 1;
550dec27d64SStefano Zampini     }
551a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
552dec27d64SStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",test,i,ord);
553a13144ffSStefano Zampini #endif
554637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5557d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5567d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5577d871cd7SStefano Zampini         break;
5587d871cd7SStefano Zampini       }
559637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
560637e8532SStefano Zampini         sneighs = PETSC_FALSE;
561637e8532SStefano Zampini       } else {
562637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
563637e8532SStefano Zampini         for (k=0;k<vc;k++) {
564637e8532SStefano Zampini           if (vn[k] != en[k]) {
565637e8532SStefano Zampini             sneighs = PETSC_FALSE;
566637e8532SStefano Zampini             break;
567637e8532SStefano Zampini           }
568637e8532SStefano Zampini         }
569637e8532SStefano Zampini       }
570637e8532SStefano Zampini     }
5717d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5727d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
573a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
574dec27d64SStefano Zampini     } else if (test == ord) {
575b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
576a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
577a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
578a13144ffSStefano Zampini       } else {
579a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
580a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
581a13144ffSStefano Zampini       }
582a13144ffSStefano Zampini     }
583a13144ffSStefano Zampini   }
584b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
585b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
5867d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
587b03ebc13SStefano Zampini 
588b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
589b03ebc13SStefano Zampini   if (order != 1) {
590b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
591b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
592b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
593b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
594b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
595b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
596b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
597b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
598b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
599b03ebc13SStefano Zampini             PetscInt v = jjt[k];
600b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
601b03ebc13SStefano Zampini               found = PETSC_TRUE;
602b03ebc13SStefano Zampini               break;
603b03ebc13SStefano Zampini             }
604b03ebc13SStefano Zampini           }
605b03ebc13SStefano Zampini         }
606b03ebc13SStefano Zampini         if (!found) {
607b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
608b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
609b03ebc13SStefano Zampini         } else {
610b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
611b03ebc13SStefano Zampini         }
612b03ebc13SStefano Zampini       }
613b03ebc13SStefano Zampini     }
614b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
615b03ebc13SStefano Zampini   }
616dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
617a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
618b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
619a13144ffSStefano Zampini 
620a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6210569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
622a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6234e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
624a13144ffSStefano Zampini 
6254e64d54eSstefano_zampini   /* Mark interior nodal dofs */
626a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6274e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
628a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
629a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6304e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
631a13144ffSStefano Zampini     }
632a13144ffSStefano Zampini   }
633a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
634a13144ffSStefano Zampini 
635a13144ffSStefano Zampini   /* communicate corners and splitpoints */
636a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
637a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
638a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
639a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
640a13144ffSStefano Zampini 
641a13144ffSStefano Zampini   if (print) {
642a13144ffSStefano Zampini     IS tbz;
643a13144ffSStefano Zampini 
644a13144ffSStefano Zampini     cum = 0;
645a13144ffSStefano Zampini     for (i=0;i<nv;i++)
646a13144ffSStefano Zampini       if (sfvleaves[i])
647a13144ffSStefano Zampini         vmarks[cum++] = i;
648a13144ffSStefano Zampini 
649a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
650a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
651a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
652a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
653a13144ffSStefano Zampini   }
654a13144ffSStefano Zampini 
655a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
656a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
657a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
658a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
659a13144ffSStefano Zampini 
6604e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6614e64d54eSstefano_zampini      and interior nodal dofs */
662a13144ffSStefano Zampini   cum = 0;
663a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
664a13144ffSStefano Zampini     if (sfvleaves[i]) {
665a13144ffSStefano Zampini       vmarks[cum++] = i;
666a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
667a13144ffSStefano Zampini     }
6684e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
669a13144ffSStefano Zampini   }
6704e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
671a13144ffSStefano Zampini   if (print) {
672a13144ffSStefano Zampini     IS tbz;
673a13144ffSStefano Zampini 
674a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6754e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
676a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
677a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
678a13144ffSStefano Zampini   }
679a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
680a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
681a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
682a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
683a13144ffSStefano Zampini 
684a13144ffSStefano Zampini   /* Recompute G */
685a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
686a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
687a13144ffSStefano Zampini   if (print) {
688a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
689a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
690a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
691a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
692a13144ffSStefano Zampini   }
693a13144ffSStefano Zampini 
694a13144ffSStefano Zampini   /* Get primal dofs (if any) */
695a13144ffSStefano Zampini   cum = 0;
696a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
697a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
698a13144ffSStefano Zampini   }
699c2151214SStefano Zampini   if (fl2g) {
700c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
701c2151214SStefano Zampini   }
702a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
703a13144ffSStefano Zampini   if (print) {
704a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
705a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
706a13144ffSStefano Zampini   }
707a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
708c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
709a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
710a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
711a13144ffSStefano Zampini 
712a13144ffSStefano Zampini   /* Compute edge connectivity */
713a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
715a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
716c2151214SStefano Zampini   if (fl2g) {
717c2151214SStefano Zampini     PetscBT   btf;
718c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
719c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
720c2151214SStefano Zampini 
721c2151214SStefano Zampini     /* create CSR for all local dofs */
722c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
723c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
724c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %d. Should be %d\n",pcbddc->mat_graph->nvtxs_csr,n);
725c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
726c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
727c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
728c2151214SStefano Zampini       rest = PETSC_TRUE;
729c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
730c2151214SStefano Zampini     } else {
731c2151214SStefano Zampini       free   = PETSC_TRUE;
732c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
733c2151214SStefano Zampini       iiu[0] = 0;
734c2151214SStefano Zampini       for (i=0;i<n;i++) {
735c2151214SStefano Zampini         iiu[i+1] = i+1;
736c2151214SStefano Zampini         jju[i]   = -1;
737d904f53bSStefano Zampini       }
738c2151214SStefano Zampini     }
739c2151214SStefano Zampini 
740c2151214SStefano Zampini     /* import sizes of CSR */
741c2151214SStefano Zampini     iia[0] = 0;
742c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
743c2151214SStefano Zampini 
744c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
745c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
746c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
747c2151214SStefano Zampini     for (i=0;i<ne;i++) {
748c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
749c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
750c2151214SStefano Zampini     }
751c2151214SStefano Zampini 
752c2151214SStefano Zampini     /* iia in CSR */
753c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
754c2151214SStefano Zampini 
755c2151214SStefano Zampini     /* jja in CSR */
756c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
757c2151214SStefano Zampini     for (i=0;i<n;i++)
758c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
759c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
760c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
761c2151214SStefano Zampini 
762c2151214SStefano Zampini     /* map edge dofs connectivity */
7631e0482f5SStefano Zampini     if (jj) {
764c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
765c2151214SStefano Zampini       for (i=0;i<ne;i++) {
766c2151214SStefano Zampini         PetscInt e = idxs[i];
767c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
768c2151214SStefano Zampini       }
7691e0482f5SStefano Zampini     }
770c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
771c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
772c2151214SStefano Zampini     if (rest) {
773c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
774c2151214SStefano Zampini     }
775c2151214SStefano Zampini     if (free) {
776c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
777c2151214SStefano Zampini     }
778c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
779c2151214SStefano Zampini   } else {
780c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
781c2151214SStefano Zampini   }
782c2151214SStefano Zampini 
783a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
784a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
785213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
786a13144ffSStefano Zampini 
787a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
788c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
789a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
790a13144ffSStefano Zampini 
791c2151214SStefano Zampini   if (fl2g) {
792c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
793c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
794c2151214SStefano Zampini     for (i=0;i<nee;i++) {
795c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
796c2151214SStefano Zampini     }
797c2151214SStefano Zampini   } else {
798c2151214SStefano Zampini     eedges  = alleedges;
799c2151214SStefano Zampini     primals = allprimals;
800c2151214SStefano Zampini   }
801c2151214SStefano Zampini 
802a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
803a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
804c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
805c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
806c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
807c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
808c2151214SStefano Zampini   if (print) {
809c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
810c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
811c2151214SStefano Zampini   }
812c2151214SStefano Zampini 
813c2151214SStefano Zampini   maxsize = 0;
814a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
815a13144ffSStefano Zampini     PetscInt size,mark = i+1;
816a13144ffSStefano Zampini 
817a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
818a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
819a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
820a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
821a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
822a13144ffSStefano Zampini   }
823a13144ffSStefano Zampini 
824a13144ffSStefano Zampini   /* Find coarse edge endpoints */
825a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
826a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
827a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
828a13144ffSStefano Zampini     PetscInt mark = i+1,size;
829a13144ffSStefano Zampini 
830a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8311e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8321e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
833a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
834a13144ffSStefano Zampini     if (print) {
835a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
836a13144ffSStefano Zampini       ISView(eedges[i],NULL);
837a13144ffSStefano Zampini     }
838a13144ffSStefano Zampini     for (j=0;j<size;j++) {
839a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
840a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
841a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
842a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
843a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
844a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
845a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
846a13144ffSStefano Zampini           PetscInt  k2;
847a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
848a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
849c2151214SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %d: mark %d (ref mark %d), boundary %d\n",jjt[k2],marks[jjt[k2]],mark,!!PetscBTLookup(btb,jjt[k2]));
850c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
851c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
852c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
853a13144ffSStefano Zampini               corner = PETSC_TRUE;
854a13144ffSStefano Zampini               break;
855a13144ffSStefano Zampini             }
856a13144ffSStefano Zampini           }
857a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
858a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
859a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
860a13144ffSStefano Zampini           } else {
861a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
862a13144ffSStefano Zampini           }
863a13144ffSStefano Zampini         }
864a13144ffSStefano Zampini       }
865a13144ffSStefano Zampini     }
866a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
867a13144ffSStefano Zampini   }
868a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
869a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
870c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
871a13144ffSStefano Zampini 
872a13144ffSStefano Zampini   /* Reset marked primal dofs */
873a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
874a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
876a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini 
8780569b399SStefano Zampini   /* Now use the initial lG */
8790569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8800569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8810569b399SStefano Zampini   lG   = lGinit;
8820569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8830569b399SStefano Zampini 
884a13144ffSStefano Zampini   /* Compute extended cols indices */
885b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
886b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
887a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
888a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
889a13144ffSStefano Zampini   i   *= maxsize;
890b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
891a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
892a13144ffSStefano Zampini   eerr = PETSC_FALSE;
893a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
894b03ebc13SStefano Zampini     PetscInt size,found = 0;
895a13144ffSStefano Zampini 
896a13144ffSStefano Zampini     cum  = 0;
897a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8981e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8991e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
900a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
901b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
902a13144ffSStefano Zampini     for (j=0;j<size;j++) {
903a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
904b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
905b03ebc13SStefano Zampini         PetscInt vv = jj[k];
906b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
907b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
908b03ebc13SStefano Zampini       }
909a13144ffSStefano Zampini     }
910a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
911a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
912a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
913a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
914a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
915a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
916a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
917b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
918b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
919a13144ffSStefano Zampini       if (print) {
920a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
921a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
922a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
923a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
924a13144ffSStefano Zampini       }
925a13144ffSStefano Zampini       eerr = PETSC_TRUE;
926a13144ffSStefano Zampini     }
927a13144ffSStefano Zampini   }
9284e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
929a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
930a13144ffSStefano Zampini   if (done) {
931a13144ffSStefano Zampini     PetscInt *newprimals;
932a13144ffSStefano Zampini 
933a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
934a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
935a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
936a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
937a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9380569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
939b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
940a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
941b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
942b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
943a13144ffSStefano Zampini         PetscInt size,mark = i+1;
944a13144ffSStefano Zampini 
945a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
946a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
947c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
948a13144ffSStefano Zampini         for (j=0;j<size;j++) {
949a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
950b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
951a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
952a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
953a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
954a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
955b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
956b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
957a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
958a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
959a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
960a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
961a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
962b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
963a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
964a13144ffSStefano Zampini                   /* finally set the new corners */
965a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
966b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
967a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
968a13144ffSStefano Zampini                   }
969a13144ffSStefano Zampini                 }
970a13144ffSStefano Zampini               }
971b03ebc13SStefano Zampini             } else {
972b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
973a13144ffSStefano Zampini             }
974a13144ffSStefano Zampini           }
975a13144ffSStefano Zampini         }
976b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
977b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
978b03ebc13SStefano Zampini 
979b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
980b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
981b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
982b03ebc13SStefano Zampini             PetscInt k2;
983b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
984b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
985b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
986b03ebc13SStefano Zampini           }
987b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
988b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
989b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
990b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
991b03ebc13SStefano Zampini             }
992b03ebc13SStefano Zampini           }
993b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
994b03ebc13SStefano Zampini         }
995a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
996a13144ffSStefano Zampini       }
997a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
998a13144ffSStefano Zampini     }
999b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10000569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1001a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1002c2151214SStefano Zampini     if (fl2g) {
1003c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1004c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1005c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1006c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1007c2151214SStefano Zampini       }
1008c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1009c2151214SStefano Zampini     }
1010c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1011a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1012a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1013a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1014a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1015a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1016213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1017c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1018c2151214SStefano Zampini     if (fl2g) {
1019c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1020c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1021c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1022c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1023c2151214SStefano Zampini       }
1024c2151214SStefano Zampini     } else {
1025c2151214SStefano Zampini       eedges  = alleedges;
1026c2151214SStefano Zampini       primals = allprimals;
1027c2151214SStefano Zampini     }
1028b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1029a13144ffSStefano Zampini 
1030a13144ffSStefano Zampini     /* Mark again */
1031a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1032a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1033a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1034a13144ffSStefano Zampini 
1035a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1036a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1037a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1038a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1039a13144ffSStefano Zampini     }
1040a13144ffSStefano Zampini     if (print) {
1041a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1042a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1043a13144ffSStefano Zampini     }
1044a13144ffSStefano Zampini 
1045a13144ffSStefano Zampini     /* Recompute extended cols */
1046a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1047a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1048a13144ffSStefano Zampini       PetscInt size;
1049a13144ffSStefano Zampini 
1050a13144ffSStefano Zampini       cum  = 0;
1051a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10521e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10531e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1054a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1055a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1056a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10571e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1058a13144ffSStefano Zampini       }
1059a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1060a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1061a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1062a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1063a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1064a13144ffSStefano Zampini       if (cum != size -1) {
1065a13144ffSStefano Zampini         if (print) {
1066a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1067a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1068a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1069a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1070a13144ffSStefano Zampini         }
1071a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1072a13144ffSStefano Zampini       }
1073a13144ffSStefano Zampini     }
1074a13144ffSStefano Zampini   }
1075a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1076a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1077b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
10787d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1079a13144ffSStefano Zampini   /* an error should not occur at this point */
1080a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1081a13144ffSStefano Zampini 
10824e64d54eSstefano_zampini   /* Check the number of endpoints */
10830569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1084b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1085b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10864e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1087b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10884e64d54eSstefano_zampini 
1089b03ebc13SStefano Zampini     /* init with defaults */
1090b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10914e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10921e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10931e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
10944e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
10964e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10974e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10984e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10994e64d54eSstefano_zampini         PetscInt vv = jj[k];
11004e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1101b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1102b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11034e64d54eSstefano_zampini         }
11044e64d54eSstefano_zampini       }
11054e64d54eSstefano_zampini     }
1106b03ebc13SStefano Zampini     if (found != 2) {
1107b03ebc13SStefano Zampini       PetscInt e;
1108b03ebc13SStefano Zampini       if (fl2g) {
1109b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1110b03ebc13SStefano Zampini       } else {
1111b03ebc13SStefano Zampini         e = idxs[0];
1112b03ebc13SStefano Zampini       }
1113b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1114b03ebc13SStefano Zampini     }
1115eee23b56SStefano Zampini 
1116eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1117b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1118b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1119b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1120b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1121b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1122b03ebc13SStefano Zampini     }
1123eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11244e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1125b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %d: ce %d, corners (%d,%d)\n",i,cedges[i],corners[2*i],corners[2*i+1]);
11264e64d54eSstefano_zampini   }
11270569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11284e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11294e64d54eSstefano_zampini 
1130a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1131a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1132a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1133a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1134a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1135a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1136a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1137a13144ffSStefano Zampini 
1138a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1139a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1140a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1141a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1142a13144ffSStefano Zampini       if (emax < emarks[j]) {
1143a13144ffSStefano Zampini         emax = emarks[j];
1144a13144ffSStefano Zampini         eemax = j;
1145a13144ffSStefano Zampini       }
1146a13144ffSStefano Zampini     }
1147a13144ffSStefano Zampini     /* not relevant for edges */
1148a13144ffSStefano Zampini     if (!eemax) continue;
1149a13144ffSStefano Zampini 
1150a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1151a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1152c2151214SStefano Zampini         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %d and %d) connected through the %d nodal dof at edge dof %d\n",marks[jj[j]]-1,eemax,i,jj[j]);
1153a13144ffSStefano Zampini       }
1154a13144ffSStefano Zampini     }
1155a13144ffSStefano Zampini   }
1156a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1157a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1158a13144ffSStefano Zampini #endif
1159a13144ffSStefano Zampini 
1160a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1161a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1162a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1163a13144ffSStefano Zampini   extmem *= maxsize;
1164a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1165a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1166a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1167a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1168a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1169213b8bfaSStefano Zampini 
1170a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1171a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1172a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1173a13144ffSStefano Zampini         mark = marks[jj[j]];
1174a13144ffSStefano Zampini 
1175a13144ffSStefano Zampini     /* not relevant */
1176a13144ffSStefano Zampini     if (!mark) continue;
1177a13144ffSStefano Zampini 
1178a13144ffSStefano Zampini     /* import extended row */
1179a13144ffSStefano Zampini     mark--;
1180a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1181a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1182a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1183a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1184a13144ffSStefano Zampini     extrowcum[mark] += size;
1185a13144ffSStefano Zampini   }
1186a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1187213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1188213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1189213b8bfaSStefano Zampini 
1190213b8bfaSStefano Zampini   /* Compress extrows */
1191a13144ffSStefano Zampini   cum  = 0;
1192a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1193a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1194a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1195a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1196a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1197a13144ffSStefano Zampini   }
1198a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1199a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1200a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1201a13144ffSStefano Zampini 
1202a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1203a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1204a13144ffSStefano Zampini 
1205a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1206a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1207c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1208c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1209a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1210a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1211a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12121e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1214a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1215213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1216a13144ffSStefano Zampini 
1217a13144ffSStefano Zampini   /* Defaults to identity */
1218c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1220a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1222a13144ffSStefano Zampini 
12231e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12241e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12251e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12261e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12271e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12281e0482f5SStefano Zampini     IS                     wis,gwis;
12291e0482f5SStefano Zampini     PetscInt               cnv,cne;
12301e0482f5SStefano Zampini 
12311e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12321e0482f5SStefano Zampini     if (fl2g) {
12331e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12341e0482f5SStefano Zampini     } else {
12351e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12361e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12371e0482f5SStefano Zampini     }
12381e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12391e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12401e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12411e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12421e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12431e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12441e0482f5SStefano Zampini 
12451e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12461e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12471e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12481e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12491e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12501e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12511e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12521e0482f5SStefano Zampini 
12531e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12541e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12551e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12561e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12571e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12581e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12591e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12601e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12611e0482f5SStefano Zampini   }
1262213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
12631e0482f5SStefano Zampini 
12641e0482f5SStefano Zampini #if defined(PRINT_GDET)
12651e0482f5SStefano Zampini   inc = 0;
12661e0482f5SStefano Zampini   lev = pcbddc->current_level;
12671e0482f5SStefano Zampini #endif
1268213b8bfaSStefano Zampini 
1269213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1270a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1271a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12721e0482f5SStefano Zampini     IS          cornersis = NULL;
12731e0482f5SStefano Zampini     PetscScalar cvals[2];
1274a13144ffSStefano Zampini 
12751e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12761e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12771e0482f5SStefano Zampini     }
12781e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1279a13144ffSStefano Zampini     if (Gins && GKins) {
1280a13144ffSStefano Zampini       PetscScalar    *data;
1281a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1282a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1283a13144ffSStefano Zampini 
1284a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1285a13144ffSStefano Zampini       /* H1 */
1286a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1287a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1288a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1289a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1290a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1291a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1292a13144ffSStefano Zampini       /* complement */
1293a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12941e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1295213b8bfaSStefano Zampini       if (ncc + nch != nrc) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %d and Gins %d does not match %d for coarse edge %d",ncc,nch,nrc,i);
1296213b8bfaSStefano Zampini       if (ncc != 1 && pcbddc->nedcG) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the coarse discrete gradient for coarse edge %d with ncc %d",i,ncc);
1297a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1298a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1299a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini       /* coarse discrete gradient */
13021e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13031e0482f5SStefano Zampini         PetscInt cols[2];
13041e0482f5SStefano Zampini 
13051e0482f5SStefano Zampini         cols[0] = 2*i;
13061e0482f5SStefano Zampini         cols[1] = 2*i+1;
13071e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13081e0482f5SStefano Zampini       }
1309a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1310a13144ffSStefano Zampini     }
1311a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1312a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1314a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1315a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1316a13144ffSStefano Zampini   }
1317213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1318a13144ffSStefano Zampini 
1319a13144ffSStefano Zampini   /* Start assembling */
1320a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13211e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13221e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13231e0482f5SStefano Zampini   }
1324a13144ffSStefano Zampini 
1325a13144ffSStefano Zampini   /* Free */
1326c2151214SStefano Zampini   if (fl2g) {
1327c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1328c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1329c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1330c2151214SStefano Zampini     }
1331c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1332c2151214SStefano Zampini   }
1333eee23b56SStefano Zampini 
1334eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1335eee23b56SStefano Zampini   {
1336eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1337eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1338eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1339eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1340eee23b56SStefano Zampini 
1341eee23b56SStefano Zampini     /* find first primal edge */
1342eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1343eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1344eee23b56SStefano Zampini     } else {
1345eee23b56SStefano Zampini       if (fl2g) {
1346eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1347eee23b56SStefano Zampini       }
1348eee23b56SStefano Zampini       idxs = cedges;
1349eee23b56SStefano Zampini     }
1350eee23b56SStefano Zampini     cum = 0;
1351eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1352eee23b56SStefano Zampini 
1353eee23b56SStefano Zampini     /* adapt connected components */
1354eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1355eee23b56SStefano Zampini     graph->cptr[0] = 0;
1356eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1357eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1358eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1359eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1360eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1361eee23b56SStefano Zampini         ncc++;
1362eee23b56SStefano Zampini         lc--;
1363eee23b56SStefano Zampini         cum++;
1364eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1365eee23b56SStefano Zampini       }
1366eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1367eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1368eee23b56SStefano Zampini       ncc++;
1369eee23b56SStefano Zampini     }
1370eee23b56SStefano Zampini     graph->ncc = ncc;
1371eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1372eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1373eee23b56SStefano Zampini     }
1374eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1375eee23b56SStefano Zampini   }
1376213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1377c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1378c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1379213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1380eee23b56SStefano Zampini 
1381c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1382a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1383a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1384b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1385b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1386a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1387a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1388a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1389a13144ffSStefano Zampini 
1390a13144ffSStefano Zampini   /* Complete assembling */
1391a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13921e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13931e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13941e0482f5SStefano Zampini #if 0
13951e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
13961e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
13971e0482f5SStefano Zampini #endif
13981e0482f5SStefano Zampini   }
1399a13144ffSStefano Zampini 
1400a13144ffSStefano Zampini   /* set change of basis */
1401213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1402a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1403a13144ffSStefano Zampini 
1404a13144ffSStefano Zampini   PetscFunctionReturn(0);
1405a13144ffSStefano Zampini }
1406a13144ffSStefano Zampini 
1407d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1408d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1409d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1410d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1411d8203eabSStefano Zampini {
1412d8203eabSStefano Zampini   PetscErrorCode ierr;
1413d8203eabSStefano Zampini   PetscInt       i;
1414d8203eabSStefano Zampini 
1415d8203eabSStefano Zampini   PetscFunctionBegin;
1416d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1417d8203eabSStefano Zampini     PetscInt first,last;
1418d8203eabSStefano Zampini 
1419d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
142086fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1421d8203eabSStefano Zampini     if (i>=first && i < last) {
1422d8203eabSStefano Zampini       PetscScalar *data;
1423d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1424d8203eabSStefano Zampini       if (!has_const) {
1425d8203eabSStefano Zampini         data[i-first] = 1.;
1426d8203eabSStefano Zampini       } else {
142786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1429d8203eabSStefano Zampini       }
1430d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1431d8203eabSStefano Zampini     }
1432d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1433d8203eabSStefano Zampini   }
1434d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1435d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1436d8203eabSStefano Zampini     PetscInt first,last;
1437ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1438d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1439d8203eabSStefano Zampini     if (i>=first && i < last) {
1440d8203eabSStefano Zampini       PetscScalar *data;
1441d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1442d8203eabSStefano Zampini       if (!has_const) {
1443d8203eabSStefano Zampini         data[i-first] = 0.;
1444d8203eabSStefano Zampini       } else {
144586fa73c5SStefano Zampini         data[2*i-first] = 0.;
144686fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1447d8203eabSStefano Zampini       }
1448d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1449d8203eabSStefano Zampini     }
1450d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1451ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1452d8203eabSStefano Zampini   }
1453d8203eabSStefano Zampini   PetscFunctionReturn(0);
1454d8203eabSStefano Zampini }
1455d8203eabSStefano Zampini 
14568ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1457669cc0f4SStefano Zampini {
1458a198735bSStefano Zampini   Mat                    loc_divudotp;
1459fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14608ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1461669cc0f4SStefano Zampini   PetscScalar            *vals;
1462669cc0f4SStefano Zampini   const PetscScalar      *array;
1463a040e873SStefano Zampini   PetscInt               i,maxneighs,maxsize;
1464a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14651ae86dd6SStefano Zampini   PetscMPIInt            rank;
1466a198735bSStefano Zampini   PetscErrorCode         ierr;
1467669cc0f4SStefano Zampini 
1468669cc0f4SStefano Zampini   PetscFunctionBegin;
1469a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1470a040e873SStefano Zampini   ierr = MPIU_Allreduce(&n_neigh,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
14718037d520SStefano Zampini   if (!maxneighs) {
14728037d520SStefano Zampini     ierr  = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14738037d520SStefano Zampini     *nnsp = NULL;
14748037d520SStefano Zampini     PetscFunctionReturn(0);
1475669cc0f4SStefano Zampini   }
1476669cc0f4SStefano Zampini   maxsize = 0;
1477a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
1478669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1479669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1480669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14818ae0ca82SStefano Zampini   if (!transpose) {
14828ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14838ae0ca82SStefano Zampini   } else {
14848ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14858ae0ca82SStefano Zampini   }
1486669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14871ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1488d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1489669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1490ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
14918ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1492669cc0f4SStefano Zampini   }
1493d8203eabSStefano Zampini 
1494669cc0f4SStefano Zampini   /* compute local quad vec */
1495a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
14968ae0ca82SStefano Zampini   if (!transpose) {
1497a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
14988ae0ca82SStefano Zampini   } else {
14998ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15008ae0ca82SStefano Zampini   }
1501669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15028ae0ca82SStefano Zampini   if (!transpose) {
1503a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15048ae0ca82SStefano Zampini   } else {
15058ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15068ae0ca82SStefano Zampini   }
1507fa23a32eSStefano Zampini   if (vl2l) {
1508187c917aSStefano Zampini     Mat        lA;
1509187c917aSStefano Zampini     VecScatter sc;
1510187c917aSStefano Zampini 
1511187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1512187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
1513187c917aSStefano Zampini     ierr = VecScatterCreate(v,vl2l,vins,NULL,&sc);CHKERRQ(ierr);
1514187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1515187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1516187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1517fa23a32eSStefano Zampini   } else {
1518fa23a32eSStefano Zampini     vins = v;
1519fa23a32eSStefano Zampini   }
1520fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1521669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15229a962809SStefano Zampini 
15231ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15241ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1525a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) {
1526669cc0f4SStefano Zampini     const PetscInt    *idxs;
1527669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1528669cc0f4SStefano Zampini 
1529a040e873SStefano Zampini     idxs = shared[i];
1530a040e873SStefano Zampini     nn   = n_shared[i];
1531669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15321ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1533669cc0f4SStefano Zampini     idx  = -(idx+1);
1534669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1535669cc0f4SStefano Zampini   }
1536a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1537fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1538fa23a32eSStefano Zampini   if (vl2l) {
1539187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1540fa23a32eSStefano Zampini   }
1541669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1542669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini 
1544669cc0f4SStefano Zampini   /* assemble near null space */
1545669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1546669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1547669cc0f4SStefano Zampini   }
1548669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1549669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
15503272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
1551ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1552669cc0f4SStefano Zampini   }
1553669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1554669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1555669cc0f4SStefano Zampini }
1556669cc0f4SStefano Zampini 
15577620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15587620a527SStefano Zampini {
15597620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15607620a527SStefano Zampini   PetscErrorCode ierr;
15617620a527SStefano Zampini 
15627620a527SStefano Zampini   PetscFunctionBegin;
15637620a527SStefano Zampini   if (primalv) {
15647620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15657620a527SStefano Zampini       IS list[2], newp;
15667620a527SStefano Zampini 
15677620a527SStefano Zampini       list[0] = primalv;
15687620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15697620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
15707620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
15717620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
15727620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15737620a527SStefano Zampini     } else {
15747620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
15757620a527SStefano Zampini     }
15767620a527SStefano Zampini   }
15777620a527SStefano Zampini   PetscFunctionReturn(0);
15787620a527SStefano Zampini }
1579669cc0f4SStefano Zampini 
15801c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15811c7a958bSStefano Zampini {
15821c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15831c7a958bSStefano Zampini 
15841c7a958bSStefano Zampini   PetscFunctionBegin;
15851c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15861c7a958bSStefano Zampini   PetscFunctionReturn(0);
15871c7a958bSStefano Zampini }
1588674ae819SStefano Zampini 
15891f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15901f4df5f7SStefano Zampini {
15911f4df5f7SStefano Zampini   PetscErrorCode ierr;
15921f4df5f7SStefano Zampini   Vec            local,global;
15931f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15941f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15955c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15961f4df5f7SStefano Zampini 
15971f4df5f7SStefano Zampini   PetscFunctionBegin;
15985c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
15995c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16005c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16011f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
160221ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16031f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16046a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16056a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16066a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16076a8fc67bSStefano Zampini     }
16086a8fc67bSStefano Zampini     goto boundary;
16096a8fc67bSStefano Zampini   }
16105c5e10d6SStefano Zampini 
16111f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16121f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16131f4df5f7SStefano Zampini       PetscInt i;
16141f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16151f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16161f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16171f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16181f4df5f7SStefano Zampini       }
16191f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16201f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16211f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16221f4df5f7SStefano Zampini     }
16231f4df5f7SStefano Zampini   } else {
162421ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
162521ef3d20SStefano Zampini       DM dm;
162621ef3d20SStefano Zampini 
162721ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
162821ef3d20SStefano Zampini       if (!dm) {
162921ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
163021ef3d20SStefano Zampini       }
163121ef3d20SStefano Zampini       if (dm) {
163221ef3d20SStefano Zampini         IS      *fields;
163321ef3d20SStefano Zampini         PetscInt nf,i;
163421ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
163521ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
163621ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
163721ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
163821ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
163921ef3d20SStefano Zampini         }
164021ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
164121ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
164221ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
164321ef3d20SStefano Zampini         PetscContainer   c;
164421ef3d20SStefano Zampini 
164521ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
164621ef3d20SStefano Zampini         if (c) {
164721ef3d20SStefano Zampini           MatISLocalFields lf;
164821ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
164921ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
165021ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16511f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1652986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
165321ef3d20SStefano Zampini           if (i > 1) {
1654986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16551f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16561f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16571f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16581f4df5f7SStefano Zampini             }
16591f4df5f7SStefano Zampini           }
166021ef3d20SStefano Zampini         }
166121ef3d20SStefano Zampini       }
16627a0e7b2cSstefano_zampini     } else {
16637a0e7b2cSstefano_zampini       PetscInt i;
16647a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16657a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16667a0e7b2cSstefano_zampini       }
16671f4df5f7SStefano Zampini     }
1668986cdee1SStefano Zampini   }
16691f4df5f7SStefano Zampini 
16705c5e10d6SStefano Zampini boundary:
16711f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16721f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16737a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16747a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16751f4df5f7SStefano Zampini   }
16761f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16771f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16787a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16797a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16801f4df5f7SStefano Zampini   }
16811f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16821f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16831f4df5f7SStefano Zampini   }
16841f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16851f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16867620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16877620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16887620a527SStefano Zampini     IS        primalv = NULL;
16897620a527SStefano Zampini     PetscInt  i;
16908361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
16917a0e7b2cSstefano_zampini 
16927620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
16937620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
16947620a527SStefano Zampini     }
16957620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
16968361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
16977620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
16987620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
16997620a527SStefano Zampini   }
17007620a527SStefano Zampini   /* early stage corner detection */
17017620a527SStefano Zampini   {
17027620a527SStefano Zampini     DM dm;
17037620a527SStefano Zampini 
17047620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17057620a527SStefano Zampini     if (dm) {
17067620a527SStefano Zampini       PetscBool isda;
17077620a527SStefano Zampini 
17087620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17097620a527SStefano Zampini       if (isda) {
17107620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17117620a527SStefano Zampini         IS                     corners;
17127620a527SStefano Zampini         Mat                    lA;
17137620a527SStefano Zampini 
1714d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17157620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17167620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17177620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
1718fa55603eSStefano Zampini         if (l2l && corners) {
17197620a527SStefano Zampini           const PetscInt *idx;
172072ed36d8SStefano Zampini           PetscInt       dof,bs,*idxout,n;
17217620a527SStefano Zampini 
172272ed36d8SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17237620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17247620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17257620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
172672ed36d8SStefano Zampini           if (bs == dof) {
17277620a527SStefano Zampini             ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17287620a527SStefano Zampini             ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
172972ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
173072ed36d8SStefano Zampini             PetscInt i,d;
173172ed36d8SStefano Zampini 
173272ed36d8SStefano Zampini             ierr = PetscMalloc1(dof*n,&idxout);CHKERRQ(ierr);
173372ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
173472ed36d8SStefano Zampini             ierr = ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout);CHKERRQ(ierr);
173572ed36d8SStefano Zampini 
173672ed36d8SStefano Zampini             bs = 1;
173772ed36d8SStefano Zampini             n *= dof;
173872ed36d8SStefano Zampini           }
17397620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1740d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17417620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17427620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
17437620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
17441c7a958bSStefano Zampini           pcbddc->corner_selected = PETSC_TRUE;
1745fa55603eSStefano Zampini         } else if (corners) { /* not from DMDA */
1746d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17477620a527SStefano Zampini         }
17487620a527SStefano Zampini       }
17497620a527SStefano Zampini     }
17507620a527SStefano Zampini   }
17511c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
17521c7a958bSStefano Zampini     DM dm;
17531c7a958bSStefano Zampini 
17541c7a958bSStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17551c7a958bSStefano Zampini     if (!dm) {
17561c7a958bSStefano Zampini       ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17571c7a958bSStefano Zampini     }
17581c7a958bSStefano Zampini     if (dm) {
17591c7a958bSStefano Zampini       Vec            vcoords;
17601c7a958bSStefano Zampini       PetscSection   section;
17611c7a958bSStefano Zampini       PetscReal      *coords;
17621c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
17631c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
17641c7a958bSStefano Zampini 
17651c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
1766e87a4003SBarry Smith       ierr = DMGetSection(dm,&section);CHKERRQ(ierr);
17671c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
17681c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
17691c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
17701c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
17711c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
17721c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
17731c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
17741c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
17751c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
17761c7a958bSStefano Zampini         PetscInt          i;
17771c7a958bSStefano Zampini         const PetscScalar *v;
17781c7a958bSStefano Zampini 
17791c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
17801c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
17811c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
17821c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
17831c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
17841c7a958bSStefano Zampini       }
17851c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
17861c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
17871c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
17881c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
17891c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
17901c7a958bSStefano Zampini     }
17911c7a958bSStefano Zampini   }
17927a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
17937a0e7b2cSstefano_zampini }
17947a0e7b2cSstefano_zampini 
17957a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
17967a0e7b2cSstefano_zampini {
17977a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
17987a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
17997a0e7b2cSstefano_zampini   IS              nis;
18007a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18017a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18027a0e7b2cSstefano_zampini   PetscBool       *ld;
18037a0e7b2cSstefano_zampini 
18047a0e7b2cSstefano_zampini   PetscFunctionBegin;
18057a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18067a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
18077a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18087a0e7b2cSstefano_zampini     /* init rootdata with true */
18097a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
18107a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
18117a0e7b2cSstefano_zampini   } else {
18127a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
18137a0e7b2cSstefano_zampini   }
18147a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18157a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18167a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18177a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18187a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18197a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18207a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18217a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18227a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18237a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18247a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18257a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18267a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18277a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18287a0e7b2cSstefano_zampini   } else {
18297a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18307a0e7b2cSstefano_zampini   }
18317a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18327a0e7b2cSstefano_zampini     if (ld[i])
18337a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18347a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18357a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18367a0e7b2cSstefano_zampini   *is  = nis;
18371f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18381f4df5f7SStefano Zampini }
18391f4df5f7SStefano Zampini 
18403e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18413e589ea0SStefano Zampini {
18423e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18433e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18443e589ea0SStefano Zampini   PetscErrorCode    ierr;
18453e589ea0SStefano Zampini 
18463e589ea0SStefano Zampini   PetscFunctionBegin;
18473e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18483e589ea0SStefano Zampini     PetscFunctionReturn(0);
18493e589ea0SStefano Zampini   }
18503e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18513e589ea0SStefano Zampini     Vec swap;
18523e589ea0SStefano Zampini 
18533e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18543e589ea0SStefano Zampini     swap = pcbddc->work_change;
18553e589ea0SStefano Zampini     pcbddc->work_change = r;
18563e589ea0SStefano Zampini     r = swap;
18573e589ea0SStefano Zampini   }
18583e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18593e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18603e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18613e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18623e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18633e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18643e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1865f913dca9SStefano Zampini     pcbddc->work_change = r;
18663e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18673e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18683e589ea0SStefano Zampini   }
18693e589ea0SStefano Zampini   PetscFunctionReturn(0);
18703e589ea0SStefano Zampini }
18713e589ea0SStefano Zampini 
1872a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1873a3df083aSStefano Zampini {
1874a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1875a3df083aSStefano Zampini   PetscErrorCode          ierr;
1876a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1877a3df083aSStefano Zampini 
1878a3df083aSStefano Zampini   PetscFunctionBegin;
1879a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1880a3df083aSStefano Zampini   if (transpose) {
1881a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1882a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1883a3df083aSStefano Zampini   } else {
1884a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1885a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1886a3df083aSStefano Zampini   }
1887a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1888a3df083aSStefano Zampini   if (apply_right) {
1889a3df083aSStefano Zampini     const PetscScalar *ax;
1890a3df083aSStefano Zampini     PetscInt          nl,i;
1891a3df083aSStefano Zampini 
1892a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1893a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1894a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1895a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1896a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1897a3df083aSStefano Zampini       PetscScalar    sum,val;
1898a3df083aSStefano Zampini       const PetscInt *idxs;
1899a3df083aSStefano Zampini       PetscInt       nz,j;
1900a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1901a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1902a3df083aSStefano Zampini       sum = 0.;
1903a3df083aSStefano Zampini       if (ctx->apply_p0) {
1904a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1905a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1906a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1907a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1908a3df083aSStefano Zampini         }
1909a3df083aSStefano Zampini       } else {
1910a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1911a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1912a3df083aSStefano Zampini         }
1913a3df083aSStefano Zampini       }
1914a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1915a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1916a3df083aSStefano Zampini     }
1917a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1918a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1919a3df083aSStefano Zampini   }
1920a3df083aSStefano Zampini   if (transpose) {
1921a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1922a3df083aSStefano Zampini   } else {
1923a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1924a3df083aSStefano Zampini   }
1925a3df083aSStefano Zampini   if (reset_x) {
1926a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1927a3df083aSStefano Zampini   }
1928a3df083aSStefano Zampini   if (apply_left) {
1929a3df083aSStefano Zampini     PetscScalar *ay;
1930a3df083aSStefano Zampini     PetscInt    i;
1931a3df083aSStefano Zampini 
1932a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1933a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1934a3df083aSStefano Zampini       PetscScalar    sum,val;
1935a3df083aSStefano Zampini       const PetscInt *idxs;
1936a3df083aSStefano Zampini       PetscInt       nz,j;
1937a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1938a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1939a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1940a3df083aSStefano Zampini       if (ctx->apply_p0) {
1941a3df083aSStefano Zampini         sum = 0.;
1942a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1943a3df083aSStefano Zampini           sum += ay[idxs[j]];
1944a3df083aSStefano Zampini           ay[idxs[j]] += val;
1945a3df083aSStefano Zampini         }
1946a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1947a3df083aSStefano Zampini       } else {
1948a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1949a3df083aSStefano Zampini           ay[idxs[j]] += val;
1950a3df083aSStefano Zampini         }
1951a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1952a3df083aSStefano Zampini       }
1953a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1954a3df083aSStefano Zampini     }
1955a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1956a3df083aSStefano Zampini   }
1957a3df083aSStefano Zampini   PetscFunctionReturn(0);
1958a3df083aSStefano Zampini }
1959a3df083aSStefano Zampini 
1960a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1961a3df083aSStefano Zampini {
1962a3df083aSStefano Zampini   PetscErrorCode ierr;
1963a3df083aSStefano Zampini 
1964a3df083aSStefano Zampini   PetscFunctionBegin;
1965a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1966a3df083aSStefano Zampini   PetscFunctionReturn(0);
1967a3df083aSStefano Zampini }
1968a3df083aSStefano Zampini 
1969a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1970a3df083aSStefano Zampini {
1971a3df083aSStefano Zampini   PetscErrorCode ierr;
1972a3df083aSStefano Zampini 
1973a3df083aSStefano Zampini   PetscFunctionBegin;
1974a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1975a3df083aSStefano Zampini   PetscFunctionReturn(0);
1976a3df083aSStefano Zampini }
1977a3df083aSStefano Zampini 
1978a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1979a3df083aSStefano Zampini {
1980a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1981a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1982a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1983a3df083aSStefano Zampini   PetscErrorCode          ierr;
1984a3df083aSStefano Zampini 
1985a3df083aSStefano Zampini   PetscFunctionBegin;
1986a3df083aSStefano Zampini   if (!restore) {
19871dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1988a3df083aSStefano Zampini     PetscScalar        *work;
1989b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1990a3df083aSStefano Zampini 
19919a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
19929a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1993a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1994a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1995a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1996a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1997a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1998a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1999a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2000a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2001a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2002a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2003a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2004a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2005059032f7SStefano Zampini     if (reuse) {
2006a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20071dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2008059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2009059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2010059032f7SStefano Zampini       PetscInt               i;
2011059032f7SStefano Zampini 
2012059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2013059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2014059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2015059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2016059032f7SStefano Zampini       }
2017059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20181dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2019059032f7SStefano Zampini     }
2020a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2021a3df083aSStefano Zampini     ctx->work = work;
2022a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2023a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2024a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2025a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2026a3df083aSStefano Zampini 
2027a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2028a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2029a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2030a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2031a3df083aSStefano Zampini   } else {
20321dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20331dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20341dd7afcfSStefano Zampini     }
2035a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2036a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2037a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20381dd7afcfSStefano Zampini     ctx->A = NULL;
20391dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20401dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20411dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20421dd7afcfSStefano Zampini     if (ctx->free) {
2043059032f7SStefano Zampini       PetscInt i;
20441dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2045059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2046059032f7SStefano Zampini       }
2047059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2048059032f7SStefano Zampini     }
2049a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2050a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2051a3df083aSStefano Zampini   }
2052a3df083aSStefano Zampini   PetscFunctionReturn(0);
2053a3df083aSStefano Zampini }
2054a3df083aSStefano Zampini 
2055a3df083aSStefano Zampini /* used just in bddc debug mode */
2056a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2057a3df083aSStefano Zampini {
2058a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2059a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2060a3df083aSStefano Zampini   Mat            An;
2061a3df083aSStefano Zampini   PetscErrorCode ierr;
2062a3df083aSStefano Zampini 
2063a3df083aSStefano Zampini   PetscFunctionBegin;
2064a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2065a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2066a3df083aSStefano Zampini   if (is1) {
20677dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2068a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2069a3df083aSStefano Zampini   } else {
2070a3df083aSStefano Zampini     *B = An;
2071a3df083aSStefano Zampini   }
2072a3df083aSStefano Zampini   PetscFunctionReturn(0);
2073a3df083aSStefano Zampini }
2074a3df083aSStefano Zampini 
20751cf9b237SStefano Zampini /* TODO: add reuse flag */
20761cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20771cf9b237SStefano Zampini {
20781cf9b237SStefano Zampini   Mat            Bt;
20791cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20801cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20811cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20821cf9b237SStefano Zampini   PetscBool      flg_row;
20831cf9b237SStefano Zampini   PetscErrorCode ierr;
20841cf9b237SStefano Zampini 
20851cf9b237SStefano Zampini   PetscFunctionBegin;
20861cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
20871cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
20881cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
20891cf9b237SStefano Zampini   nnz = n;
20901cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
20911cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
20921cf9b237SStefano Zampini   }
20931cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
20941cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
20951cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
20961cf9b237SStefano Zampini   nnz = 0;
20971cf9b237SStefano Zampini   bii[0] = 0;
20981cf9b237SStefano Zampini   for (i=0;i<n;i++) {
20991cf9b237SStefano Zampini     PetscInt j;
21001cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21011cf9b237SStefano Zampini       PetscScalar entry = a[j];
21023272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21031cf9b237SStefano Zampini         bij[nnz] = ij[j];
21041cf9b237SStefano Zampini         bdata[nnz] = entry;
21051cf9b237SStefano Zampini         nnz++;
21061cf9b237SStefano Zampini       }
21071cf9b237SStefano Zampini     }
21081cf9b237SStefano Zampini     bii[i+1] = nnz;
21091cf9b237SStefano Zampini   }
21101cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21111cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21121cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21131cf9b237SStefano Zampini   {
21141cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21151cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21161cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21171cf9b237SStefano Zampini   }
21183272d46bSStefano Zampini   if (*B == A) {
21193272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21203272d46bSStefano Zampini   }
21211cf9b237SStefano Zampini   *B = Bt;
21221cf9b237SStefano Zampini   PetscFunctionReturn(0);
21231cf9b237SStefano Zampini }
21241cf9b237SStefano Zampini 
21258361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21264f1b2e48SStefano Zampini {
2127c80a6c00SStefano Zampini   Mat                    B = NULL;
2128c80a6c00SStefano Zampini   DM                     dm;
21294f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21304f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21314f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2132c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21334f1b2e48SStefano Zampini   PetscInt               i,n;
21344f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2135c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21364f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21374f1b2e48SStefano Zampini 
21384f1b2e48SStefano Zampini   PetscFunctionBegin;
2139a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2140a2eca866SStefano Zampini   if (cc) *cc = NULL;
2141a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2142c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2143c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2144c80a6c00SStefano Zampini   if (!dm) {
2145c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2146c80a6c00SStefano Zampini   }
2147c80a6c00SStefano Zampini   if (dm) {
2148c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2149c80a6c00SStefano Zampini   }
21508361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
21518361f951SStefano Zampini 
2152c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2153c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2154c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2155c80a6c00SStefano Zampini     IS             cellNumbering;
2156c80a6c00SStefano Zampini     const PetscInt *cellNum;
2157c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2158c80a6c00SStefano Zampini     PetscSection   section;
2159c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2160c80a6c00SStefano Zampini     PetscSF        sfPoint;
2161c80a6c00SStefano Zampini     PetscErrorCode ierr;
2162c80a6c00SStefano Zampini 
2163c80a6c00SStefano Zampini     PetscFunctionBegin;
2164c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2165c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2166c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2167c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2168c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2169c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2170c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2171c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2172c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2173c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2174c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2175c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2176956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2177c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2178c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2179c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2180c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2181c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2182c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2183c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2184c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21855cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2186c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2187c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2188c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2189c80a6c00SStefano Zampini           *pBuf = point;
2190c80a6c00SStefano Zampini         }
2191c80a6c00SStefano Zampini       }
2192c80a6c00SStefano Zampini       n++;
2193c80a6c00SStefano Zampini     }
2194c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2195c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2196c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2197c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2198c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2199c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2200c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2201c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2202c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2203c80a6c00SStefano Zampini     }
2204c80a6c00SStefano Zampini     xadj[n] = size;
2205c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2206c80a6c00SStefano Zampini     /* Clean up */
2207c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2208c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2209c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2210c80a6c00SStefano Zampini     graph->xadj = xadj;
2211c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2212c80a6c00SStefano Zampini   } else {
2213c80a6c00SStefano Zampini     Mat       A;
22148361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2215c80a6c00SStefano Zampini 
2216c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
221763c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2218a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
221963c961adSStefano Zampini       PetscFunctionReturn(0);
222063c961adSStefano Zampini     }
22214f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22224f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22231cf9b237SStefano Zampini       PetscBool isseqdense;
22241cf9b237SStefano Zampini 
22251cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22261cf9b237SStefano Zampini       if (!isseqdense) {
22274f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22281cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22291cf9b237SStefano Zampini         PetscScalar *array;
22301cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22311cf9b237SStefano Zampini 
22321cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22331cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22341cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22351cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22361cf9b237SStefano Zampini           PetscInt j;
22371cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22381cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22391cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22401cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22411cf9b237SStefano Zampini           }
22421cf9b237SStefano Zampini         }
22431cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22449d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22451cf9b237SStefano Zampini       }
22464f1b2e48SStefano Zampini     } else {
2247c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22484f1b2e48SStefano Zampini       B = A;
22494f1b2e48SStefano Zampini     }
22504f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22514f1b2e48SStefano Zampini 
22524f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22534f1b2e48SStefano Zampini     if (filter) {
22544f1b2e48SStefano Zampini       PetscScalar *data;
22554f1b2e48SStefano Zampini       PetscInt    j,cum;
22564f1b2e48SStefano Zampini 
22574f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22584f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22594f1b2e48SStefano Zampini       cum = 0;
22604f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22614f1b2e48SStefano Zampini         PetscInt t;
22624f1b2e48SStefano Zampini 
22634f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22644f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22654f1b2e48SStefano Zampini             continue;
22664f1b2e48SStefano Zampini           }
22674f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22684f1b2e48SStefano Zampini         }
22694f1b2e48SStefano Zampini         t = xadj_filtered[i];
22704f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22714f1b2e48SStefano Zampini         cum += t;
22724f1b2e48SStefano Zampini       }
22734f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22744f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22754f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22764f1b2e48SStefano Zampini     } else {
22774f1b2e48SStefano Zampini       graph->xadj = xadj;
22784f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22794f1b2e48SStefano Zampini     }
2280c80a6c00SStefano Zampini   }
2281c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2282c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2283c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2284c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2285c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2286c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22874f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22884f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2289c80a6c00SStefano Zampini 
22904f1b2e48SStefano Zampini   /* partial clean up */
22914f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2292c80a6c00SStefano Zampini   if (B) {
2293c80a6c00SStefano Zampini     PetscBool flg_row;
22944f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22954f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
22964f1b2e48SStefano Zampini   }
2297c80a6c00SStefano Zampini   if (isplex) {
2298c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2299c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2300c80a6c00SStefano Zampini   }
23014f1b2e48SStefano Zampini 
23024f1b2e48SStefano Zampini   /* get back data */
2303c80a6c00SStefano Zampini   if (isplex) {
2304c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2305c80a6c00SStefano Zampini     if (cc || primalv) {
2306c80a6c00SStefano Zampini       Mat          A;
2307c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2308c80a6c00SStefano Zampini       PetscSection subSection;
2309c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2310c80a6c00SStefano Zampini 
2311c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2312c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2313c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2314c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2315c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2316c80a6c00SStefano Zampini 
2317c80a6c00SStefano Zampini       cids[0] = 0;
2318c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2319c80a6c00SStefano Zampini         PetscInt j;
2320c80a6c00SStefano Zampini 
2321c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2322c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2323c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2324c80a6c00SStefano Zampini 
2325c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2326c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2327c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2328c80a6c00SStefano Zampini 
2329c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2330c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2331c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2332c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2333c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2334c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2335c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2336c80a6c00SStefano Zampini               } else { /* cross-vertex */
2337c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2338c80a6c00SStefano Zampini               }
2339c80a6c00SStefano Zampini             }
2340c80a6c00SStefano Zampini           }
2341c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2342c80a6c00SStefano Zampini         }
2343c80a6c00SStefano Zampini         cids[i+1] = cum;
2344c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2345c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2346c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2347c80a6c00SStefano Zampini         }
2348c80a6c00SStefano Zampini       }
2349c80a6c00SStefano Zampini       if (cc) {
2350c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2351c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2352c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2353c80a6c00SStefano Zampini         }
2354c80a6c00SStefano Zampini         *cc = cc_n;
2355c80a6c00SStefano Zampini       }
2356c80a6c00SStefano Zampini       if (primalv) {
2357c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2358c80a6c00SStefano Zampini       }
2359c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2360c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2361c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2362c80a6c00SStefano Zampini     }
2363c80a6c00SStefano Zampini   } else {
23641cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23651cf9b237SStefano Zampini     if (cc) {
23664f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23674f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23684f1b2e48SStefano 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);
23694f1b2e48SStefano Zampini       }
23704f1b2e48SStefano Zampini       *cc = cc_n;
23711cf9b237SStefano Zampini     }
2372c80a6c00SStefano Zampini   }
23734f1b2e48SStefano Zampini   /* clean up graph */
23744f1b2e48SStefano Zampini   graph->xadj = 0;
23754f1b2e48SStefano Zampini   graph->adjncy = 0;
23764f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23774f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23784f1b2e48SStefano Zampini }
23794f1b2e48SStefano Zampini 
23805408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23815408967cSStefano Zampini {
23825408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23835408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2384dee84bffSStefano Zampini   IS             dirIS = NULL;
23854f1b2e48SStefano Zampini   PetscInt       i;
23865408967cSStefano Zampini   PetscErrorCode ierr;
23875408967cSStefano Zampini 
23885408967cSStefano Zampini   PetscFunctionBegin;
2389dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
23905408967cSStefano Zampini   if (zerodiag) {
23915408967cSStefano Zampini     Mat            A;
23925408967cSStefano Zampini     Vec            vec3_N;
23935408967cSStefano Zampini     PetscScalar    *vals;
23945408967cSStefano Zampini     const PetscInt *idxs;
2395d12d3064SStefano Zampini     PetscInt       nz,*count;
23965408967cSStefano Zampini 
23975408967cSStefano Zampini     /* p0 */
23985408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
23995408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24005408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24015408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24024f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24035408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24045408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24055408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24065408967cSStefano Zampini     /* v_I */
24075408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24085408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24095408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24105408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24115408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24125408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24135408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24145408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24155408967cSStefano Zampini     if (dirIS) {
24165408967cSStefano Zampini       PetscInt n;
24175408967cSStefano Zampini 
24185408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24195408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24205408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24215408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24225408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24235408967cSStefano Zampini     }
24245408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24255408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24265408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24275408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2428669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24295408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24305408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24319a962809SStefano 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]));
24325408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24335408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2434d12d3064SStefano Zampini 
2435d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2436d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2437d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2438d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2439d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2440d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24419a962809SStefano 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]);
2442d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2443d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24445408967cSStefano Zampini   }
2445dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24465408967cSStefano Zampini 
24475408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24485408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24494f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24505408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24514f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24525408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2453f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2454f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
245513903a91SSatish Balay     if (val != -PetscGlobalRank-i) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %d instead of %g\n",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i);
2456f2a566d8SStefano Zampini   }
24575408967cSStefano Zampini   PetscFunctionReturn(0);
24585408967cSStefano Zampini }
24595408967cSStefano Zampini 
2460339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2461339f8db1SStefano Zampini {
2462339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24634edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2464b0f5fe93SStefano Zampini   PetscInt       nz,n;
24654edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24664edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2467339f8db1SStefano Zampini   PetscErrorCode ierr;
2468339f8db1SStefano Zampini 
2469339f8db1SStefano Zampini   PetscFunctionBegin;
24709f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24719f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2472a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2473a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2474a3df083aSStefano Zampini   }
2475a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2476a3df083aSStefano Zampini   pcbddc->benign_n = 0;
247728b8efb1Sstefano_zampini 
247828b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
24794f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
24804f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24814f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24821ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24834f1b2e48SStefano Zampini   */
24844f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
24854f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
248640fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24877fbe2174Sstefano_zampini     IS       iP = NULL;
24884f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
24894f1b2e48SStefano Zampini 
249028b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
249128b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
249228b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
249328b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
24944f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
24954f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
24964f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24974f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2498ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
24997fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25007fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
25017fbe2174Sstefano_zampini     if (iP) {
25027fbe2174Sstefano_zampini       IS newpressures;
25037fbe2174Sstefano_zampini 
25047fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
25057fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
25067fbe2174Sstefano_zampini       pressures = newpressures;
25077fbe2174Sstefano_zampini     }
250840fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
250940fa8d13SStefano Zampini     if (!sorted) {
251040fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
251140fa8d13SStefano Zampini     }
251240fa8d13SStefano Zampini   } else {
251340fa8d13SStefano Zampini     pressures = NULL;
251440fa8d13SStefano Zampini   }
251597d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
251697d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
251727b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
251897d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2519339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2520339f8db1SStefano Zampini   if (!sorted) {
2521339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2522339f8db1SStefano Zampini   }
25234edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25244edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2525339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25264f1b2e48SStefano Zampini   if (!nz) {
25274f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25284f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
252940fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
253040fa8d13SStefano Zampini   }
25314f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25324f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25334f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25344f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
25351f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25361f4df5f7SStefano Zampini   interior_dofs    = NULL;
25374edc6404Sstefano_zampini   nneu             = 0;
25384edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25394edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25404edc6404Sstefano_zampini   }
25413369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25424edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25431f4df5f7SStefano Zampini     PetscInt n,i,j;
25441f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25451f4df5f7SStefano Zampini     PetscInt *iwork;
25461f4df5f7SStefano Zampini 
25471f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25481f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25491f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25501f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
255190648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25521f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25531f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25541f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25551f4df5f7SStefano Zampini       if (!iwork[i])
25561f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25571f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25581f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25591f4df5f7SStefano Zampini   }
25604f1b2e48SStefano Zampini   if (has_null_pressures) {
25614f1b2e48SStefano Zampini     IS             *subs;
25624edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
25631f4df5f7SStefano Zampini     const PetscInt *idxs;
25641f4df5f7SStefano Zampini     PetscScalar    *array;
25651f4df5f7SStefano Zampini     Vec            *work;
25661f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25674f1b2e48SStefano Zampini 
25684f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
25694f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
25701f4df5f7SStefano 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) */
25714edc6404Sstefano_zampini     if (checkb) {
25721f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
25731f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
25741f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25751f4df5f7SStefano Zampini       /* work[0] = 1_p */
25761f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
25771f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
25781f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25791f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
25801f4df5f7SStefano Zampini       /* work[0] = 1_v */
25811f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
25821f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
25831f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
25841f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
25851f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
25861f4df5f7SStefano Zampini     }
25874f1b2e48SStefano Zampini     if (nsubs > 1) {
25884f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
25894f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
25904f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
25914f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
25924f1b2e48SStefano Zampini         PetscInt               nl;
25934f1b2e48SStefano Zampini 
25944f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
25954f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
25964f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
25974f1b2e48SStefano Zampini         if (nl) {
25984f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
25994f1b2e48SStefano Zampini 
26004edc6404Sstefano_zampini           if (checkb) {
26011f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
26021f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
26031f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
26041f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26051f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26061f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26071f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
26081f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
26091f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
26101f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
26111f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
26121f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
26131f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26141f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
26151f4df5f7SStefano Zampini                 break;
26161f4df5f7SStefano Zampini               }
26171f4df5f7SStefano Zampini             }
26181f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26191f4df5f7SStefano Zampini           }
26206632bad2Sstefano_zampini           if (valid && nneu) {
26216632bad2Sstefano_zampini             const PetscInt *idxs;
26221f4df5f7SStefano Zampini             PetscInt       nzb;
26231f4df5f7SStefano Zampini 
26246632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26256632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26266632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26271f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
26281f4df5f7SStefano Zampini           }
26291f4df5f7SStefano Zampini           if (valid && pressures) {
26304f1b2e48SStefano Zampini             IS t_pressure_subs;
26314f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26324f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
26334f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26344f1b2e48SStefano Zampini           }
26354f1b2e48SStefano Zampini           if (valid) {
26364f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
26374f1b2e48SStefano Zampini             pcbddc->benign_n++;
26384f1b2e48SStefano Zampini           } else {
26394f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
26404f1b2e48SStefano Zampini           }
26414f1b2e48SStefano Zampini         }
26424f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
26434f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
26444f1b2e48SStefano Zampini       }
26454f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
26464f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
26471f4df5f7SStefano Zampini 
26486632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
26491f4df5f7SStefano Zampini       if (valid && pressures) {
26504f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
26514f1b2e48SStefano Zampini       }
26524edc6404Sstefano_zampini       if (valid && checkb) {
26531f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
26541f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
26551f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26561f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
26571f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26581f4df5f7SStefano Zampini             valid = PETSC_FALSE;
26591f4df5f7SStefano Zampini             break;
26601f4df5f7SStefano Zampini           }
26611f4df5f7SStefano Zampini         }
26621f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26631f4df5f7SStefano Zampini       }
26644f1b2e48SStefano Zampini       if (valid) {
26654f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2666ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
26674f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26684f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
26694f1b2e48SStefano Zampini       }
26704f1b2e48SStefano Zampini     }
26714edc6404Sstefano_zampini     if (checkb) {
26721f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
26734f1b2e48SStefano Zampini     }
26741f4df5f7SStefano Zampini   }
26751f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
26764f1b2e48SStefano Zampini 
26774f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2678b9b0e38cSStefano Zampini     PetscInt n;
2679b9b0e38cSStefano Zampini 
26804f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26814f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2682b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2683b9b0e38cSStefano Zampini     if (n) {
26844f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
26854f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
26864f1b2e48SStefano Zampini     }
2687b9b0e38cSStefano Zampini   }
26884f1b2e48SStefano Zampini 
26894f1b2e48SStefano Zampini   /* final check for null pressures */
26904f1b2e48SStefano Zampini   if (zerodiag && pressures) {
26914f1b2e48SStefano Zampini     PetscInt nz,np;
26924f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26934f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
26944f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
26954f1b2e48SStefano Zampini   }
26964f1b2e48SStefano Zampini 
26974f1b2e48SStefano Zampini   if (recompute_zerodiag) {
26984f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26994f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
27004f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
27014f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
27024f1b2e48SStefano Zampini     } else {
27034f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
27044f1b2e48SStefano Zampini 
27054f1b2e48SStefano Zampini       nzn = 0;
27064f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27074f1b2e48SStefano Zampini         PetscInt ns;
27084f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27094f1b2e48SStefano Zampini         nzn += ns;
27104f1b2e48SStefano Zampini       }
27114f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
27124f1b2e48SStefano Zampini       nzn = 0;
27134f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27144f1b2e48SStefano Zampini         PetscInt ns,*idxs;
27154f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27164f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27174f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
27184f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27194f1b2e48SStefano Zampini         nzn += ns;
27204f1b2e48SStefano Zampini       }
27214f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27224f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27234f1b2e48SStefano Zampini     }
27244f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27254f1b2e48SStefano Zampini   }
27264f1b2e48SStefano Zampini 
2727669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2728a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2729a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2730a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2731a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2732a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2733a198735bSStefano Zampini 
27341f4df5f7SStefano Zampini     if (pressures) {
27351f4df5f7SStefano Zampini       isused = pressures;
27361f4df5f7SStefano Zampini     } else {
27374edc6404Sstefano_zampini       isused = zerodiag_save;
27381f4df5f7SStefano Zampini     }
2739a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2740669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
27411ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
27421ae86dd6SStefano 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");
2743a198735bSStefano Zampini     n_isused = 0;
2744a198735bSStefano Zampini     if (isused) {
2745a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2746a198735bSStefano Zampini     }
2747a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2748a198735bSStefano Zampini     st = st-n_isused;
27491ae86dd6SStefano Zampini     if (n) {
2750a198735bSStefano Zampini       const PetscInt *gidxs;
2751a198735bSStefano Zampini 
27527dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2753a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2754a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2755a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2756a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2757a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
27581ae86dd6SStefano Zampini     } else {
2759a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2760a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2761a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2762a198735bSStefano Zampini     }
2763a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2764a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2765a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2766a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2767a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2768a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2769a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2770a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2771a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2772a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2773a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2774a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2775a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2776a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
27771ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27781ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27791ae86dd6SStefano Zampini   }
27804edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2781b3afcdbeSStefano Zampini 
2782b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
27834f1b2e48SStefano Zampini   if (has_null_pressures) {
27844f1b2e48SStefano Zampini     IS             zerodiagc;
27854f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
27864f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
27874f1b2e48SStefano Zampini 
27884f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2789339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2790339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2791339f8db1SStefano Zampini     /* local change of basis for pressures */
2792339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
279397d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2794339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2795339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2796339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
27974f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
27984f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
27994f1b2e48SStefano Zampini       PetscInt nzs,j;
28004f1b2e48SStefano Zampini 
28014f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
28024f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28034f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
28044f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
28054f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28064f1b2e48SStefano Zampini     }
2807339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2808e1b21442SStefano Zampini     ierr = MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2809339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2810339f8db1SStefano Zampini     /* set identity on velocities */
2811339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2812339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2813339f8db1SStefano Zampini     }
28144f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
28154f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
28169f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
28174f1b2e48SStefano 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);
2818339f8db1SStefano Zampini     /* set change on pressures */
28194f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28204f1b2e48SStefano Zampini       PetscScalar *array;
28214f1b2e48SStefano Zampini       PetscInt    nzs;
28224f1b2e48SStefano Zampini 
28234f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28244f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28254f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2826339f8db1SStefano Zampini         PetscScalar vals[2];
2827339f8db1SStefano Zampini         PetscInt    cols[2];
2828339f8db1SStefano Zampini 
2829339f8db1SStefano Zampini         cols[0] = idxs[i];
28304f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2831339f8db1SStefano Zampini         vals[0] = 1.;
2832b0f5fe93SStefano Zampini         vals[1] = 1.;
28334f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2834339f8db1SStefano Zampini       }
28354f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
28364f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
28374f1b2e48SStefano Zampini       array[nzs-1] = 1.;
28384f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
28394f1b2e48SStefano Zampini       /* store local idxs for p0 */
28404f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
28414f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2842339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
28434f1b2e48SStefano Zampini     }
2844339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2845339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2846a3df083aSStefano Zampini     /* project if needed */
2847a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28481dd7afcfSStefano Zampini       Mat M;
28491dd7afcfSStefano Zampini 
28501dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2851339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28521dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
28531dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2854a3df083aSStefano Zampini     }
28554f1b2e48SStefano Zampini     /* store global idxs for p0 */
28564f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2857339f8db1SStefano Zampini   }
2858ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28594f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2860b0f5fe93SStefano Zampini 
2861b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2862b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
286327b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
2864c69e9cc1SStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
286527b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2866339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2867339f8db1SStefano Zampini   PetscFunctionReturn(0);
2868339f8db1SStefano Zampini }
2869339f8db1SStefano Zampini 
2870015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2871efc2fbd9SStefano Zampini {
2872efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2873de9d7bd0SStefano Zampini   PetscScalar    *array;
2874efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2875efc2fbd9SStefano Zampini 
2876efc2fbd9SStefano Zampini   PetscFunctionBegin;
2877efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2878efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
28794f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2880efc2fbd9SStefano Zampini   }
2881de9d7bd0SStefano Zampini   if (get) {
2882efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
28834f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
28844f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2885efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2886de9d7bd0SStefano Zampini   } else {
2887de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2888de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2889de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2890de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2891efc2fbd9SStefano Zampini   }
2892efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2893efc2fbd9SStefano Zampini }
2894efc2fbd9SStefano Zampini 
2895c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2896c263805aSStefano Zampini {
2897c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2898c263805aSStefano Zampini   PetscErrorCode ierr;
2899c263805aSStefano Zampini 
2900c263805aSStefano Zampini   PetscFunctionBegin;
2901c263805aSStefano Zampini   /* TODO: add error checking
2902c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2903c263805aSStefano Zampini     - cannot push before pop.
29041c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2905c263805aSStefano Zampini   */
29064f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2907efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2908efc2fbd9SStefano Zampini   }
2909c263805aSStefano Zampini   if (pop) {
2910a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29114f1b2e48SStefano Zampini       IS       is_p0;
29124f1b2e48SStefano Zampini       MatReuse reuse;
2913c263805aSStefano Zampini 
2914c263805aSStefano Zampini       /* extract B_0 */
29154f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
29164f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
29174f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
29184f1b2e48SStefano Zampini       }
29194f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
29207dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2921c263805aSStefano Zampini       /* remove rows and cols from local problem */
2922c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
292397d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29244f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29254f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2926a3df083aSStefano Zampini     } else {
2927a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2928a3df083aSStefano Zampini       PetscScalar *vals;
2929a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2930a3df083aSStefano Zampini 
2931a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2932a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2933a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
29340b5adadeSStefano Zampini         PetscInt *nnz;
2935a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2936a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2937a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2938331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2939331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2940331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2941331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2942331e053bSStefano Zampini         }
2943331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2944e1b21442SStefano Zampini         ierr = MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2945331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2946331e053bSStefano Zampini       }
2947a3df083aSStefano Zampini 
2948a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2949a3df083aSStefano Zampini         PetscScalar *array;
2950a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2951a3df083aSStefano Zampini 
2952a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2953a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2954a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2955a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2956a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2957a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2958a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2959a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2960a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2961a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2962a3df083aSStefano Zampini         cum = 0;
2963a3df083aSStefano Zampini         for (j=0;j<n;j++) {
296422db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2965a3df083aSStefano Zampini             vals[cum] = array[j];
2966a3df083aSStefano Zampini             idxs_ins[cum] = j;
2967a3df083aSStefano Zampini             cum++;
2968a3df083aSStefano Zampini           }
2969a3df083aSStefano Zampini         }
2970a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2971a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2972a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2973a3df083aSStefano Zampini       }
2974a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2975a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2976a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2977a3df083aSStefano Zampini     }
2978c263805aSStefano Zampini   } else { /* push */
2979a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29804f1b2e48SStefano Zampini       PetscInt i;
29814f1b2e48SStefano Zampini 
29824f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
29834f1b2e48SStefano Zampini         PetscScalar *B0_vals;
29844f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
29854f1b2e48SStefano Zampini 
29864f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29874f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29887b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29894f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
29904f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29914f1b2e48SStefano Zampini       }
2992c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2993c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2994a3df083aSStefano Zampini     } else {
2995a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2996a3df083aSStefano Zampini     }
2997c263805aSStefano Zampini   }
2998c263805aSStefano Zampini   PetscFunctionReturn(0);
2999c263805aSStefano Zampini }
3000c263805aSStefano Zampini 
300108122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3002b1b3d7a2SStefano Zampini {
3003b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
300408122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
300508122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
300608122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
300708122e43SStefano Zampini   PetscScalar     *work,lwork;
300808122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
300908122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3010bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
30111b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3012f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
301308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
301408122e43SStefano Zampini   PetscReal       *rwork;
301508122e43SStefano Zampini #endif
3016b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3017b1b3d7a2SStefano Zampini 
3018b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3019b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3020af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3021bd2a564bSStefano 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);
302243371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
302306a4e24aSStefano Zampini 
3024fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3025fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3026fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3027fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30281575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3029fd14bc51SStefano Zampini   }
3030fd14bc51SStefano Zampini 
3031e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
3032e496cd5dSStefano Zampini     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
3033e496cd5dSStefano Zampini   }
3034e496cd5dSStefano Zampini 
303508122e43SStefano Zampini   /* max size of subsets */
303608122e43SStefano Zampini   mss = 0;
303708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
303808122e43SStefano Zampini     PetscInt subset_size;
3039862806e4SStefano Zampini 
304008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
304108122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
304208122e43SStefano Zampini   }
304308122e43SStefano Zampini 
304408122e43SStefano Zampini   /* min/max and threshold */
304508122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3046f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
304708122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3048f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3049bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3050f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3051f6f667cfSStefano Zampini   }
305208122e43SStefano Zampini 
305308122e43SStefano Zampini   /* allocate lapack workspace */
305408122e43SStefano Zampini   cum = cum2 = 0;
305508122e43SStefano Zampini   maxneigs = 0;
305608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
305708122e43SStefano Zampini     PetscInt n,subset_size;
3058f6f667cfSStefano Zampini 
305908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
306008122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
30619162d606SStefano Zampini     cum += subset_size;
30629162d606SStefano Zampini     cum2 += subset_size*n;
306308122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
306408122e43SStefano Zampini   }
306508122e43SStefano Zampini   if (mss) {
3066bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
306708122e43SStefano Zampini       PetscBLASInt B_itype = 1;
306808122e43SStefano Zampini       PetscBLASInt B_N = mss;
30694c6709b3SStefano Zampini       PetscReal    zero = 0.0;
30704c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
307108122e43SStefano Zampini 
307208122e43SStefano Zampini       B_lwork = -1;
307308122e43SStefano Zampini       S = NULL;
307408122e43SStefano Zampini       St = NULL;
3075a58a30b4SStefano Zampini       eigs = NULL;
3076a58a30b4SStefano Zampini       eigv = NULL;
3077a58a30b4SStefano Zampini       B_iwork = NULL;
3078a58a30b4SStefano Zampini       B_ifail = NULL;
3079d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3080d1710679SStefano Zampini       rwork = NULL;
3081d1710679SStefano Zampini #endif
30828bec7fa6SStefano Zampini       thresh = 1.0;
308308122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
308408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
308508122e43SStefano 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));
308608122e43SStefano Zampini #else
308708122e43SStefano 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));
308808122e43SStefano Zampini #endif
308908122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
309008122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3091bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
309208122e43SStefano Zampini   } else {
309308122e43SStefano Zampini     lwork = 0;
309408122e43SStefano Zampini   }
309508122e43SStefano Zampini 
309608122e43SStefano Zampini   nv = 0;
3097d62866d3SStefano 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) */
3098d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
309908122e43SStefano Zampini   }
31004c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3101f6f667cfSStefano Zampini   if (allocated_S_St) {
3102f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3103f6f667cfSStefano Zampini   }
3104f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
310508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
310608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
310708122e43SStefano Zampini #endif
31089162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
31099162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
31109162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
311108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
31129162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
311308122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
311408122e43SStefano Zampini 
311508122e43SStefano Zampini   maxneigs = 0;
311672b8c272SStefano Zampini   cum = cumarray = 0;
31179162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
31189162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3119d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
312008122e43SStefano Zampini     const PetscInt *idxs;
312108122e43SStefano Zampini 
3122d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
312308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
312408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
312508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
312608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31279162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31289162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
312908122e43SStefano Zampini     }
3130d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
313108122e43SStefano Zampini   }
313208122e43SStefano Zampini 
313308122e43SStefano Zampini   if (mss) { /* multilevel */
313408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
313508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
313608122e43SStefano Zampini   }
313708122e43SStefano Zampini 
3138bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3139bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
314008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
314108122e43SStefano Zampini     const PetscInt *idxs;
31429d54b7f4SStefano Zampini     PetscReal      upper,lower;
3143862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
314408122e43SStefano Zampini     PetscBLASInt   B_N;
3145aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3146bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
314708122e43SStefano Zampini 
31489d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
31499d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3150bd2a564bSStefano Zampini       lower = uthresh;
31519d54b7f4SStefano Zampini     } else {
3152bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3153bd2a564bSStefano Zampini       upper = 1./uthresh;
31549d54b7f4SStefano Zampini       lower = 0.;
31559d54b7f4SStefano Zampini     }
3156862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3157ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3158f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3159bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3160bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3161bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3162bd2a564bSStefano Zampini       Mat T;
3163bd2a564bSStefano Zampini 
3164bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3165bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3166bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3167bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3168bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3169bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3170bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3171bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3172bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3173bd2a564bSStefano Zampini             PetscInt       nz,k;
3174bd2a564bSStefano Zampini             const PetscInt *idxs;
3175bd2a564bSStefano Zampini 
3176bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3177bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3178bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3179bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3180bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3181bd2a564bSStefano Zampini             }
3182bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3183bd2a564bSStefano Zampini           }
3184bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3185bd2a564bSStefano Zampini           break;
3186bd2a564bSStefano Zampini         }
3187bd2a564bSStefano Zampini       }
3188bd2a564bSStefano Zampini     }
3189bd2a564bSStefano Zampini 
3190f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3191bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3192aff50787SStefano Zampini         PetscInt j,k;
3193aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3194aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3195aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
319608122e43SStefano Zampini         }
319708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3198aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3199aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3200aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3201aff50787SStefano Zampini           }
320208122e43SStefano Zampini         }
320308122e43SStefano Zampini       } else {
320408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
320508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
320608122e43SStefano Zampini       }
32078bec7fa6SStefano Zampini     } else {
3208f6f667cfSStefano Zampini       S = Sarray + cumarray;
3209f6f667cfSStefano Zampini       St = Starray + cumarray;
32108bec7fa6SStefano Zampini     }
3211aff50787SStefano Zampini     /* see if we can save some work */
3212b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3213aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3214aff50787SStefano Zampini     }
3215aff50787SStefano Zampini 
3216b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3217aff50787SStefano Zampini       B_neigs = 0;
3218aff50787SStefano Zampini     } else {
3219bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
322008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3221f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
32224c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
32239552c7c7SStefano Zampini         PetscInt     nmin_s;
3224bd2a564bSStefano Zampini         PetscBool    compute_range;
3225bd2a564bSStefano Zampini 
32269036ceccSStefano Zampini         B_neigs = 0;
3227bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3228bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
322908122e43SStefano Zampini 
3230fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
32319036ceccSStefano Zampini           PetscInt nc = 0;
3232d16cbb6bSStefano Zampini 
32339036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
32349036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
32359036ceccSStefano Zampini           }
32369036ceccSStefano 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);
3237b7ab4a40SStefano Zampini         }
3238b7ab4a40SStefano Zampini 
323908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3240b7ab4a40SStefano Zampini         if (compute_range) {
3241d16cbb6bSStefano Zampini 
3242d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3243bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
324408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32459d54b7f4SStefano 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));
324608122e43SStefano Zampini #else
32479d54b7f4SStefano 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));
324808122e43SStefano Zampini #endif
324943371fb9SStefano Zampini             ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3250bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
32519036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3252bd2a564bSStefano Zampini             PetscReal bb[2];
3253bd2a564bSStefano Zampini 
3254bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3255bd2a564bSStefano Zampini             switch (recipe) {
3256bd2a564bSStefano Zampini             case 0:
3257bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3258bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3259bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3260bd2a564bSStefano 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));
3261bd2a564bSStefano Zampini #else
3262bd2a564bSStefano 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));
3263bd2a564bSStefano Zampini #endif
326443371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3265bd2a564bSStefano Zampini               break;
3266bd2a564bSStefano Zampini             case 1:
3267bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3268bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3269bd2a564bSStefano 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));
3270bd2a564bSStefano Zampini #else
3271bd2a564bSStefano 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));
3272bd2a564bSStefano Zampini #endif
327343371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3274bd2a564bSStefano Zampini               if (!scal) {
32759036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3276bd2a564bSStefano Zampini 
3277aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3278bd2a564bSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3279bd2a564bSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3280bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3281bd2a564bSStefano 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));
3282bd2a564bSStefano Zampini #else
3283bd2a564bSStefano 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));
3284bd2a564bSStefano Zampini #endif
328543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3286bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3287bd2a564bSStefano Zampini               }
3288bd2a564bSStefano Zampini               break;
32899036ceccSStefano Zampini             case 2:
32909036ceccSStefano Zampini               if (scal) {
32919036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
32929036ceccSStefano Zampini                 bb[1] = 0;
32939036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
32949036ceccSStefano 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));
32959036ceccSStefano Zampini #else
32969036ceccSStefano 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));
32979036ceccSStefano Zampini #endif
329843371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
32999036ceccSStefano Zampini               } else {
33009036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
33019036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
33029036ceccSStefano Zampini 
33039036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
33049036ceccSStefano Zampini                 if (lthresh > 0.0) {
33059036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
33069036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
33079036ceccSStefano Zampini 
33089036ceccSStefano Zampini                   import = PETSC_TRUE;
33099036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33109036ceccSStefano 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));
33119036ceccSStefano Zampini #else
33129036ceccSStefano 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));
33139036ceccSStefano Zampini #endif
331443371fb9SStefano Zampini                   ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33159036ceccSStefano Zampini                 }
33169036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
33179036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
33189036ceccSStefano Zampini                 if (import) {
33199036ceccSStefano Zampini                   ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33209036ceccSStefano Zampini                   ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33219036ceccSStefano Zampini                 }
33229036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33239036ceccSStefano 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));
33249036ceccSStefano Zampini #else
33259036ceccSStefano 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));
33269036ceccSStefano Zampini #endif
332743371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33289036ceccSStefano Zampini                 B_neigs += B_neigs2;
33299036ceccSStefano Zampini               }
33309036ceccSStefano Zampini               break;
33319036ceccSStefano Zampini             case 3:
33329036ceccSStefano Zampini               if (scal) {
33339036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
33349036ceccSStefano Zampini               } else {
33359036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
33369036ceccSStefano Zampini               }
33379036ceccSStefano Zampini               if (!scal) {
33389036ceccSStefano Zampini                 bb[0] = uthresh;
33399036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
33409036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33419036ceccSStefano 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));
33429036ceccSStefano Zampini #else
33439036ceccSStefano 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));
33449036ceccSStefano Zampini #endif
334543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33469036ceccSStefano Zampini               }
33479036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
33489036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
33499036ceccSStefano Zampini 
33509036ceccSStefano Zampini                 B_IL = 1;
33519036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
33529036ceccSStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33539036ceccSStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33549036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
33559036ceccSStefano 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));
33569036ceccSStefano Zampini #else
33579036ceccSStefano 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));
33589036ceccSStefano Zampini #endif
335943371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
33609036ceccSStefano Zampini                 B_neigs += B_neigs2;
33619036ceccSStefano Zampini               }
33629036ceccSStefano Zampini               break;
336348cebe81SStefano Zampini             case 4:
336448cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
336548cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
336648cebe81SStefano 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));
336748cebe81SStefano Zampini #else
336848cebe81SStefano 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));
336948cebe81SStefano Zampini #endif
337043371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
337148cebe81SStefano Zampini               {
337248cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
337348cebe81SStefano Zampini 
337448cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
337548cebe81SStefano Zampini                 ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
337648cebe81SStefano Zampini                 ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
337748cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
337848cebe81SStefano 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));
337948cebe81SStefano Zampini #else
338048cebe81SStefano 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));
338148cebe81SStefano Zampini #endif
338243371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
338348cebe81SStefano Zampini                 B_neigs += B_neigs2;
338448cebe81SStefano Zampini               }
338548cebe81SStefano Zampini               break;
338680db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
338780db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
338880db8efeSStefano 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));
338980db8efeSStefano Zampini #else
339080db8efeSStefano 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));
339180db8efeSStefano Zampini #endif
339243371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
339380db8efeSStefano Zampini               {
339480db8efeSStefano Zampini                 PetscInt e,k,ne;
339580db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
339680db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
339780db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
339880db8efeSStefano Zampini                     eigs[ne] = eigs[e];
339980db8efeSStefano Zampini                     ne++;
340080db8efeSStefano Zampini                   }
340180db8efeSStefano Zampini                 }
340280db8efeSStefano Zampini                 ierr = PetscMemcpy(eigv,S,B_N*ne*sizeof(PetscScalar));CHKERRQ(ierr);
340380db8efeSStefano Zampini                 B_neigs = ne;
340480db8efeSStefano Zampini               }
340580db8efeSStefano Zampini               break;
3406bd2a564bSStefano Zampini             default:
3407bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3408bd2a564bSStefano Zampini               break;
3409bd2a564bSStefano Zampini             }
3410bd2a564bSStefano Zampini           }
3411bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3412d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3413d16cbb6bSStefano Zampini           B_IL = 1;
3414d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34159d54b7f4SStefano 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));
3416d16cbb6bSStefano Zampini #else
34179d54b7f4SStefano 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));
3418d16cbb6bSStefano Zampini #endif
341943371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3420b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3421b7ab4a40SStefano Zampini           PetscInt k;
3422b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3423b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3424b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3425b7ab4a40SStefano Zampini           nmin = nmax;
3426b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3427b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3428b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3429b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3430b7ab4a40SStefano Zampini           }
3431d16cbb6bSStefano Zampini         }
343208122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
343308122e43SStefano Zampini         if (B_ierr) {
34346c4ed002SBarry 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);
34356c4ed002SBarry 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);
34366c4ed002SBarry 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);
343708122e43SStefano Zampini         }
343808122e43SStefano Zampini 
343908122e43SStefano Zampini         if (B_neigs > nmax) {
3440fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3441bd2a564bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);CHKERRQ(ierr);
3442fd14bc51SStefano Zampini           }
3443bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
344408122e43SStefano Zampini           B_neigs = nmax;
344508122e43SStefano Zampini         }
344608122e43SStefano Zampini 
34479552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
34489552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
34499036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
345008122e43SStefano Zampini 
34519d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3452bd2a564bSStefano Zampini             if (scal) {
3453bd2a564bSStefano Zampini               B_IU = nmin_s;
3454bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3455bd2a564bSStefano Zampini             } else {
3456f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
34579d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3458bd2a564bSStefano Zampini             }
34599d54b7f4SStefano Zampini           } else {
34609d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
34619d54b7f4SStefano Zampini             B_IU = nmin_s;
34629d54b7f4SStefano Zampini           }
3463fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3464fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %d. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);
3465fd14bc51SStefano Zampini           }
3466bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
34671ae86dd6SStefano Zampini             PetscInt j,k;
346808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
34691ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
34701ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
34711ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
347208122e43SStefano Zampini               }
347308122e43SStefano Zampini             }
347408122e43SStefano Zampini           } else {
347508122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
347608122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
347708122e43SStefano Zampini           }
347808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
347908122e43SStefano 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_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
348108122e43SStefano 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_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
348308122e43SStefano Zampini #endif
348443371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
348508122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
348608122e43SStefano Zampini           B_neigs += B_neigs2;
348708122e43SStefano Zampini         }
348808122e43SStefano Zampini         if (B_ierr) {
34896c4ed002SBarry 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);
34906c4ed002SBarry 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);
34916c4ed002SBarry 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);
349208122e43SStefano Zampini         }
3493fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3494ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
349508122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
349608122e43SStefano Zampini             if (eigs[j] == 0.0) {
3497ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
349808122e43SStefano Zampini             } else {
34999d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3500ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
35019d54b7f4SStefano Zampini               } else {
35029d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
35039d54b7f4SStefano Zampini               }
3504fd14bc51SStefano Zampini             }
350508122e43SStefano Zampini           }
350608122e43SStefano Zampini         }
3507bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3508aff50787SStefano Zampini     }
35096c3e6151SStefano Zampini     /* change the basis back to the original one */
35106c3e6151SStefano Zampini     if (sub_schurs->change) {
351172b8c272SStefano Zampini       Mat change,phi,phit;
35126c3e6151SStefano Zampini 
351303dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
35146c3e6151SStefano Zampini         PetscInt ii;
35156c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
35166c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
35176c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3518684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3519684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3520684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3521684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3522684229deSStefano Zampini #else
35236c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3524684229deSStefano Zampini #endif
35256c3e6151SStefano Zampini           }
35266c3e6151SStefano Zampini         }
35276c3e6151SStefano Zampini       }
352872b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
35296c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
353072b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
35316c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
35326c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
35336c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
35346c3e6151SStefano Zampini     }
35358bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
35368bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
35379162d606SStefano Zampini     if (B_neigs) {
35389162d606SStefano 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);
3539fd14bc51SStefano Zampini 
3540fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
35419552c7c7SStefano Zampini         PetscInt ii;
35429552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3543ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
35449552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3545ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3546ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3547ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3548ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3549ac47001eSStefano Zampini #else
3550ac47001eSStefano 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);
3551ac47001eSStefano Zampini #endif
35529552c7c7SStefano Zampini           }
35539552c7c7SStefano Zampini         }
3554fd14bc51SStefano Zampini       }
35559162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
35569162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
35579162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
35589162d606SStefano Zampini       cum++;
355908122e43SStefano Zampini     }
356008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
356108122e43SStefano Zampini     /* shift for next computation */
356208122e43SStefano Zampini     cumarray += subset_size*subset_size;
356308122e43SStefano Zampini   }
3564fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3565fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3566fd14bc51SStefano Zampini   }
356708122e43SStefano Zampini 
356808122e43SStefano Zampini   if (mss) {
356908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
357008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3571f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3572f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3573f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
357408122e43SStefano Zampini   }
3575f6f667cfSStefano Zampini   if (allocated_S_St) {
3576f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3577f6f667cfSStefano Zampini   }
3578f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
357908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
358008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
358108122e43SStefano Zampini #endif
358208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
35831b968477SStefano Zampini     PetscInt maxneigs_r;
3584b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
35859b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
358608122e43SStefano Zampini   }
358743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
358808122e43SStefano Zampini   PetscFunctionReturn(0);
358908122e43SStefano Zampini }
3590b1b3d7a2SStefano Zampini 
3591c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3592c8587f34SStefano Zampini {
35938629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3594c8587f34SStefano Zampini   PetscErrorCode ierr;
3595c8587f34SStefano Zampini 
3596c8587f34SStefano Zampini   PetscFunctionBegin;
3597f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
35985e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3599c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3600c8587f34SStefano Zampini 
3601684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
36020fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3603684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3604c8587f34SStefano Zampini 
36058629588bSStefano Zampini   /*
36068629588bSStefano Zampini      Setup local correction and local part of coarse basis.
36078629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
36088629588bSStefano Zampini   */
360947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
36108629588bSStefano Zampini 
36118629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
36128629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
36138629588bSStefano Zampini 
36148629588bSStefano Zampini   /* free */
36158629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3616c8587f34SStefano Zampini   PetscFunctionReturn(0);
3617c8587f34SStefano Zampini }
3618c8587f34SStefano Zampini 
3619674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3620674ae819SStefano Zampini {
3621674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3622674ae819SStefano Zampini   PetscErrorCode ierr;
3623674ae819SStefano Zampini 
3624674ae819SStefano Zampini   PetscFunctionBegin;
3625674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
362630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3627674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3628785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3629674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3630f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3631f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3632785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
363363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
363463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3635674ae819SStefano Zampini   PetscFunctionReturn(0);
3636674ae819SStefano Zampini }
3637674ae819SStefano Zampini 
3638674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3639674ae819SStefano Zampini {
3640674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
36414f1b2e48SStefano Zampini   PetscInt       i;
3642674ae819SStefano Zampini   PetscErrorCode ierr;
3643674ae819SStefano Zampini 
3644674ae819SStefano Zampini   PetscFunctionBegin;
36451e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
36461e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3647a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3648b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3649674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
365016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
36511dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3652674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3653669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3654fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
36559326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
36564f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
36574f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
36584f1b2e48SStefano Zampini   }
3659e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
36604f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3661e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3662c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
36638af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
36641c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3665674ae819SStefano Zampini   PetscFunctionReturn(0);
3666674ae819SStefano Zampini }
3667674ae819SStefano Zampini 
3668674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3669674ae819SStefano Zampini {
3670674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3671674ae819SStefano Zampini   PetscErrorCode ierr;
3672674ae819SStefano Zampini 
3673674ae819SStefano Zampini   PetscFunctionBegin;
3674674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
367558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3676ca92afb2SStefano Zampini     PetscScalar *array;
367706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
367806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
367958da7f69SStefano Zampini   }
3680674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3681674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
368215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
368315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3684674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3685674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3686674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
368706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3688674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3689674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
36908ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3691674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3692674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3693674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
36949326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
36959326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
36969326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3697f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3698727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
36990e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3700f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
370170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
370281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
37030369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
37041dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
37054f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
37068b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3707ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3708ca92afb2SStefano Zampini     PetscInt i;
3709ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3710ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3711ca92afb2SStefano Zampini     }
3712ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3713ca92afb2SStefano Zampini   }
37144f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3715674ae819SStefano Zampini   PetscFunctionReturn(0);
3716674ae819SStefano Zampini }
3717674ae819SStefano Zampini 
3718f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
37196bfb1811SStefano Zampini {
37206bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37216bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
37226bfb1811SStefano Zampini   VecType        impVecType;
37234f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
37246bfb1811SStefano Zampini   PetscErrorCode ierr;
37256bfb1811SStefano Zampini 
37266bfb1811SStefano Zampini   PetscFunctionBegin;
37274f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3728b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
37296bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3730e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3731e7b262bdSStefano Zampini   /* R nodes */
3732e7b262bdSStefano Zampini   old_size = -1;
3733e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3734e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3735e7b262bdSStefano Zampini   }
3736e7b262bdSStefano Zampini   if (n_R != old_size) {
3737e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3738e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
37396bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
37406bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
37416bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
37426bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3743e7b262bdSStefano Zampini   }
3744e7b262bdSStefano Zampini   /* local primal dofs */
3745e7b262bdSStefano Zampini   old_size = -1;
3746e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3747e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3748e7b262bdSStefano Zampini   }
3749e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3750e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
375183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3752e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
37536bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3754e7b262bdSStefano Zampini   }
3755e7b262bdSStefano Zampini   /* local explicit constraints */
3756e7b262bdSStefano Zampini   old_size = -1;
3757e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3758e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3759e7b262bdSStefano Zampini   }
3760e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3761e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
376283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
376383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
376483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
376583b7ccabSStefano Zampini   }
37666bfb1811SStefano Zampini   PetscFunctionReturn(0);
37676bfb1811SStefano Zampini }
37686bfb1811SStefano Zampini 
376947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
377088ebb749SStefano Zampini {
377125084f0cSStefano Zampini   PetscErrorCode  ierr;
377225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
377388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
377488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3775d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
377625084f0cSStefano Zampini   /* submatrices of local problem */
377780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
377806656605SStefano Zampini   /* submatrices of local coarse problem */
377906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
378025084f0cSStefano Zampini   /* working matrices */
378106656605SStefano Zampini   Mat             C_CR;
378225084f0cSStefano Zampini   /* additional working stuff */
378306656605SStefano Zampini   PC              pc_R;
3784c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
37855cbda25cSStefano Zampini   Vec             dummy_vec;
3786c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
378725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
378806656605SStefano Zampini   PetscScalar     *work;
378906656605SStefano Zampini   PetscInt        *idx_V_B;
3790ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
379106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3792ffd830a3SStefano Zampini 
379325084f0cSStefano Zampini   /* some shortcuts to scalars */
379406656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
379588ebb749SStefano Zampini 
379688ebb749SStefano Zampini   PetscFunctionBegin;
37979a962809SStefano 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");
379843371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
3799ffd830a3SStefano Zampini 
3800ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3801b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
38024f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3803b371cd4fSStefano Zampini   n_B = pcis->n_B;
3804b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
380588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
380688ebb749SStefano Zampini 
380788ebb749SStefano Zampini   /* vertices in boundary numbering */
3808785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
38090e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
38106c4ed002SBarry Smith   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",n_vertices,i);
381188ebb749SStefano Zampini 
381206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3813019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
381406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
381506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
381606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
381706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
381806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
381906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
382006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
382106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
382206656605SStefano Zampini 
382306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
382406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
38252958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
382606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
382706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
382806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3829ffd830a3SStefano Zampini   lda_rhs = n_R;
3830a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
383106656605SStefano Zampini   if (isLU || isILU || isCHOL) {
383206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3833b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3834df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3835d62866d3SStefano Zampini     MatFactorType      type;
3836d62866d3SStefano Zampini 
3837df4d28bfSStefano Zampini     F = reuse_solver->F;
38386816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3839d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3840ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
384122db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
384206656605SStefano Zampini   } else {
384306656605SStefano Zampini     F = NULL;
384406656605SStefano Zampini   }
384506656605SStefano Zampini 
3846c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3847c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3848c58f9fdbSStefano Zampini   if (F) {
3849ea799195SBarry Smith     MatSolverType solver;
3850c58f9fdbSStefano Zampini 
38513ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3852c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3853c58f9fdbSStefano Zampini   }
3854c58f9fdbSStefano Zampini 
3855ffd830a3SStefano Zampini   /* allocate workspace */
3856ffd830a3SStefano Zampini   n = 0;
3857ffd830a3SStefano Zampini   if (n_constraints) {
3858ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3859ffd830a3SStefano Zampini   }
3860ffd830a3SStefano Zampini   if (n_vertices) {
3861ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3862ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3863ffd830a3SStefano Zampini   }
38642a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
38652a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
38662a3a6641Sstefano_zampini   }
3867ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3868ffd830a3SStefano Zampini 
38695cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
38705cbda25cSStefano Zampini   dummy_vec = NULL;
38715cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
38725cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
38735cbda25cSStefano Zampini   }
38745cbda25cSStefano Zampini 
387588ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
387688ebb749SStefano Zampini   if (n_constraints) {
3877837cedc9SStefano Zampini     Mat         M3,C_B;
387806656605SStefano Zampini     IS          is_aux;
387980677318SStefano Zampini     PetscScalar *array,*array2;
388006656605SStefano Zampini 
3881f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
388280677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
388388ebb749SStefano Zampini 
388425084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
388525084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
38867dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
38877dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
388888ebb749SStefano Zampini 
388980677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
389080677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3891c58f9fdbSStefano Zampini     if (!sparserhs) {
3892ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
389388ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
389406656605SStefano Zampini         const PetscScalar *row_cmat_values;
389506656605SStefano Zampini         const PetscInt    *row_cmat_indices;
389606656605SStefano Zampini         PetscInt          size_of_constraint,j;
389788ebb749SStefano Zampini 
389806656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
389906656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3900ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
390106656605SStefano Zampini         }
390206656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
390306656605SStefano Zampini       }
3904c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3905c58f9fdbSStefano Zampini     } else {
3906c58f9fdbSStefano Zampini       Mat tC_CR;
3907c58f9fdbSStefano Zampini 
3908c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3909c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3910c58f9fdbSStefano Zampini         PetscScalar *aa;
3911c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3912c58f9fdbSStefano Zampini         PetscBool   done;
3913c58f9fdbSStefano Zampini 
3914c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
391513903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3916c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3917c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3918c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
391913903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3920c58f9fdbSStefano Zampini       } else {
3921c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3922c58f9fdbSStefano Zampini         tC_CR = C_CR;
3923c58f9fdbSStefano Zampini       }
3924c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3925c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3926c58f9fdbSStefano Zampini     }
3927ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
392806656605SStefano Zampini     if (F) {
3929a3df083aSStefano Zampini       if (need_benign_correction) {
3930df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3931a3df083aSStefano Zampini 
393272b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
393372b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3934a3df083aSStefano Zampini       }
3935c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3936a3df083aSStefano Zampini       if (need_benign_correction) {
3937a3df083aSStefano Zampini         PetscScalar        *marr;
3938df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3939a3df083aSStefano Zampini 
3940a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
39415cbda25cSStefano Zampini         if (lda_rhs != n_R) {
39425cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
39435cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
39445cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
39455cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
39465cbda25cSStefano Zampini           }
39475cbda25cSStefano Zampini         } else {
3948a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3949a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
39505cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3951a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3952a3df083aSStefano Zampini           }
39535cbda25cSStefano Zampini         }
3954a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3955a3df083aSStefano Zampini       }
395606656605SStefano Zampini     } else {
395780677318SStefano Zampini       PetscScalar *marr;
395880677318SStefano Zampini 
395980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
396006656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3961ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3962ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
396306656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
396406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
396506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
396606656605SStefano Zampini       }
396780677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
396806656605SStefano Zampini     }
3969c58f9fdbSStefano Zampini     if (sparserhs) {
3970c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3971c58f9fdbSStefano Zampini     }
3972c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
397380677318SStefano Zampini     if (!pcbddc->switch_static) {
397480677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
397580677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
397680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
397780677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3978ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
397980677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
398080677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
398180677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
398280677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
398380677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
398480677318SStefano Zampini       }
398580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
398680677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
398772b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
398880677318SStefano Zampini     } else {
3989ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3990ffd830a3SStefano Zampini         IS dummy;
3991ffd830a3SStefano Zampini 
3992ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
39937dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3994ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3995ffd830a3SStefano Zampini       } else {
399680677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
399780677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3998ffd830a3SStefano Zampini       }
399925084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
400080677318SStefano Zampini     }
400180677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
400280677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
400380677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
400480677318SStefano Zampini     if (isCHOL) {
400580677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
400680677318SStefano Zampini     } else {
400725084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
400880677318SStefano Zampini     }
4009837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
401080677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
4011837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
401272b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
4013837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
4014837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
4015f4ddd8eeSStefano Zampini   }
4016fc227af8SStefano Zampini 
4017fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
401888ebb749SStefano Zampini   if (n_vertices) {
401906656605SStefano Zampini     IS        is_aux;
4020c58f9fdbSStefano Zampini     PetscBool isseqaij;
40213a50541eSStefano Zampini 
4022b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
40236816873aSStefano Zampini       IS tis;
40246816873aSStefano Zampini 
40256816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
40266816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
40276816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
40286816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
40296816873aSStefano Zampini     } else {
40303a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
40316816873aSStefano Zampini     }
40327dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
40337dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
4034c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
4035c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
4036c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4037c58f9fdbSStefano Zampini     }
40387dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
403925084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
404088ebb749SStefano Zampini   }
404188ebb749SStefano Zampini 
404288ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4043f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
404406656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
404506656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
404606656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
404706656605SStefano Zampini     }
4048f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
404906656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
405006656605SStefano Zampini       PetscScalar *marray;
405106656605SStefano Zampini 
405206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
405306656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4054f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4055f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4056f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4057f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4058f4ddd8eeSStefano Zampini     }
4059f4ddd8eeSStefano Zampini   }
406006656605SStefano Zampini 
4061f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4062a6e023c1Sstefano_zampini     PetscScalar *marr;
406388ebb749SStefano Zampini 
4064a6e023c1Sstefano_zampini     /* memory size */
406506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4066a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4067a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4068a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4069a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4070a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
40718eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4072a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4073a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
407488ebb749SStefano Zampini     }
40753301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4076a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4077a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
40788eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4079a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
408088ebb749SStefano Zampini       }
408188ebb749SStefano Zampini     } else {
4082c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4083c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
40841b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4085c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4086c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4087c0553b1fSStefano Zampini       }
408888ebb749SStefano Zampini     }
408906656605SStefano Zampini   }
4090019a44ceSStefano Zampini 
409106656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
40924f1b2e48SStefano Zampini   p0_lidx_I = NULL;
40934f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4094d12edf2fSStefano Zampini     const PetscInt *idxs;
4095d12edf2fSStefano Zampini 
4096d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
40974f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
40984f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
40994f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
41004f1b2e48SStefano Zampini     }
4101d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4102d12edf2fSStefano Zampini   }
4103d16cbb6bSStefano Zampini 
410406656605SStefano Zampini   /* vertices */
410506656605SStefano Zampini   if (n_vertices) {
4106c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
410716f15bc4SStefano Zampini 
4108af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
410904708bb6SStefano Zampini 
411016f15bc4SStefano Zampini     if (n_R) {
411114393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
411206656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
411316f15bc4SStefano Zampini       PetscScalar  *x,*y;
411406656605SStefano Zampini 
411521eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
411614393ed6SStefano Zampini       if (need_benign_correction) {
411714393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
411814393ed6SStefano Zampini         IS                     is_p0;
411914393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
412014393ed6SStefano Zampini 
412114393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
412214393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
412314393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
4124af25d912SStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
412514393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
412614393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
41277dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
412814393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
412914393ed6SStefano Zampini       }
413014393ed6SStefano Zampini 
4131c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4132c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4133ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4134af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4135ffd830a3SStefano Zampini         } else {
4136ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4137ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4138ca92afb2SStefano Zampini           PetscInt       n;
4139ca92afb2SStefano Zampini           PetscBool      flg_row;
4140ffd830a3SStefano Zampini 
4141ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4142ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
41439d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4144ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4145ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4146ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4147ca92afb2SStefano Zampini             PetscInt j;
4148ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4149ffd830a3SStefano Zampini           }
4150ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4151ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4152ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4153ffd830a3SStefano Zampini         }
4154a3df083aSStefano Zampini         if (need_benign_correction) {
4155df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4156a3df083aSStefano Zampini           PetscScalar        *marr;
4157a3df083aSStefano Zampini 
4158a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
415914393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
416014393ed6SStefano Zampini 
416114393ed6SStefano Zampini                  | 0 0  0 | (V)
416214393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
416314393ed6SStefano Zampini                  | 0 0 -1 | (p0)
416414393ed6SStefano Zampini 
416514393ed6SStefano Zampini           */
4166df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
416714393ed6SStefano Zampini             const PetscScalar *vals;
416814393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
416914393ed6SStefano Zampini             PetscInt          n,j,nz;
417014393ed6SStefano Zampini 
4171df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4172df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
417314393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
417414393ed6SStefano Zampini             for (j=0;j<n;j++) {
417514393ed6SStefano Zampini               PetscScalar val = vals[j];
417614393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
417714393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
417814393ed6SStefano Zampini             }
417914393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4180df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
418114393ed6SStefano Zampini           }
418272b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
418372b8c272SStefano Zampini         }
4184c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4185c58f9fdbSStefano Zampini         Brhs = A_RV;
4186c58f9fdbSStefano Zampini       } else {
4187c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4188c58f9fdbSStefano Zampini 
4189c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4190fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4191c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4192c58f9fdbSStefano Zampini         } else {
4193c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4194c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4195c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4196c58f9fdbSStefano Zampini           A_RVT = A_VR;
4197c58f9fdbSStefano Zampini         }
4198c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4199c58f9fdbSStefano Zampini           PetscScalar *aa;
4200c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4201c58f9fdbSStefano Zampini           PetscBool   done;
4202c58f9fdbSStefano Zampini 
4203c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
420413903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4205c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4206c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4207c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
420813903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4209c58f9fdbSStefano Zampini         } else {
4210c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4211c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4212c58f9fdbSStefano Zampini         }
4213c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4214c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4215c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4216c58f9fdbSStefano Zampini       }
421772b8c272SStefano Zampini       if (F) {
421814393ed6SStefano Zampini         /* need to correct the rhs */
421972b8c272SStefano Zampini         if (need_benign_correction) {
422072b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
422172b8c272SStefano Zampini           PetscScalar        *marr;
422272b8c272SStefano Zampini 
4223c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
42245cbda25cSStefano Zampini           if (lda_rhs != n_R) {
42255cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
42265cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
42275cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
42285cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
42295cbda25cSStefano Zampini             }
42305cbda25cSStefano Zampini           } else {
4231a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4232a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
42335cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4234a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4235a3df083aSStefano Zampini             }
42365cbda25cSStefano Zampini           }
4237c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4238a3df083aSStefano Zampini         }
4239c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4240c58f9fdbSStefano Zampini         if (restoreavr) {
4241c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4242c58f9fdbSStefano Zampini         }
424314393ed6SStefano Zampini         /* need to correct the solution */
4244a3df083aSStefano Zampini         if (need_benign_correction) {
4245df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4246a3df083aSStefano Zampini           PetscScalar        *marr;
4247a3df083aSStefano Zampini 
4248a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
42495cbda25cSStefano Zampini           if (lda_rhs != n_R) {
42505cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
42515cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
42525cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
42535cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
42545cbda25cSStefano Zampini             }
42555cbda25cSStefano Zampini           } else {
4256a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4257a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
42585cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4259a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4260a3df083aSStefano Zampini             }
42615cbda25cSStefano Zampini           }
4262a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4263a3df083aSStefano Zampini         }
426406656605SStefano Zampini       } else {
4265c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
426606656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4267ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4268ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
426906656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
427006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
427106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
427206656605SStefano Zampini         }
4273c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
427406656605SStefano Zampini       }
427580677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4276c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4277ffd830a3SStefano Zampini       /* S_VV and S_CV */
427806656605SStefano Zampini       if (n_constraints) {
427906656605SStefano Zampini         Mat B;
428080677318SStefano Zampini 
4281ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
428280677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4283ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4284ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
428580677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
428680677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
428780677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
428880677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
428980677318SStefano Zampini         }
4290ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
429180677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
429280677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4293ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
429480677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
429506656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4296ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4297ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
429806656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
429906656605SStefano Zampini       }
4300ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4301ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4302ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4303ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4304ffd830a3SStefano Zampini       }
430506656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
430614393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
430714393ed6SStefano Zampini       if (need_benign_correction) {
4308df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
430914393ed6SStefano Zampini         PetscScalar      *marr,*sums;
431014393ed6SStefano Zampini 
431114393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4312f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4313df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
431414393ed6SStefano Zampini           const PetscScalar *vals;
431514393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
431614393ed6SStefano Zampini           PetscInt          n,j,nz;
431714393ed6SStefano Zampini 
4318df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4319df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
432014393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
432114393ed6SStefano Zampini             PetscInt k;
432214393ed6SStefano Zampini             sums[j] = 0.;
432314393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
432414393ed6SStefano Zampini           }
432514393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
432614393ed6SStefano Zampini           for (j=0;j<n;j++) {
432714393ed6SStefano Zampini             PetscScalar val = vals[j];
432814393ed6SStefano Zampini             PetscInt k;
432914393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
433014393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
433114393ed6SStefano Zampini             }
433214393ed6SStefano Zampini           }
433314393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4334df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
433514393ed6SStefano Zampini         }
433614393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4337f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
433814393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
433914393ed6SStefano Zampini       }
434080677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
434106656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
434206656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
434306656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
434406656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
434506656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
434606656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
434706656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4348d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4349019a44ceSStefano Zampini     } else {
4350d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4351d16cbb6bSStefano Zampini     }
435221eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4353d16cbb6bSStefano Zampini 
435406656605SStefano Zampini     /* coarse basis functions */
435506656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
435616f15bc4SStefano Zampini       PetscScalar *y;
435716f15bc4SStefano Zampini 
4358ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
435906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
436006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
436106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
436206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
436306656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
436406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
436506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
436606656605SStefano Zampini 
436706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
43684f1b2e48SStefano Zampini         PetscInt j;
43694f1b2e48SStefano Zampini 
437006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
437106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
437206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
437306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
437406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
43754f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
437606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
437706656605SStefano Zampini       }
437806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
437906656605SStefano Zampini     }
438004708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
438104708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
438206656605SStefano Zampini   }
43835cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
438406656605SStefano Zampini 
438506656605SStefano Zampini   if (n_constraints) {
438606656605SStefano Zampini     Mat B;
438706656605SStefano Zampini 
4388ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
438906656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
439080677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
439106656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
439206656605SStefano Zampini     if (n_vertices) {
439303dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
439480677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
439580677318SStefano Zampini       } else {
439680677318SStefano Zampini         Mat S_VCt;
439780677318SStefano Zampini 
4398ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4399ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
440072b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4401ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4402ffd830a3SStefano Zampini         }
440380677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
440480677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
440580677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
440680677318SStefano Zampini       }
440706656605SStefano Zampini     }
440806656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
440906656605SStefano Zampini     /* coarse basis functions */
441006656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
441106656605SStefano Zampini       PetscScalar *y;
441206656605SStefano Zampini 
4413ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
441406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
441506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
441606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
441706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
441806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
441906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
442006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
44214f1b2e48SStefano Zampini         PetscInt j;
44224f1b2e48SStefano Zampini 
442306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
442406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
442506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
44284f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
442906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
443006656605SStefano Zampini       }
443106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
443206656605SStefano Zampini     }
443306656605SStefano Zampini   }
443480677318SStefano Zampini   if (n_constraints) {
443580677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
443680677318SStefano Zampini   }
44374f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
443872b8c272SStefano Zampini 
443972b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
444072b8c272SStefano Zampini   if (pcbddc->benign_n) {
444172b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
444272b8c272SStefano Zampini     IS          is_dummy;
444372b8c272SStefano Zampini     PetscScalar *data;
444472b8c272SStefano Zampini     PetscInt    j;
444572b8c272SStefano Zampini 
444672b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44477dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
444872b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
444972b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
445086c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
445172b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
445272b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
445372b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
445472b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
445572b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
445672b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
445772b8c272SStefano Zampini       }
445872b8c272SStefano Zampini     }
445972b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
446072b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
446172b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
446272b8c272SStefano Zampini   }
4463019a44ceSStefano Zampini 
446406656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
44653301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4466ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4467ffd830a3SStefano Zampini     PetscScalar *marray;
446806656605SStefano Zampini 
446906656605SStefano Zampini     if (n_constraints) {
4470ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
447106656605SStefano Zampini 
4472abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
447306656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4474ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
447516f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
447606656605SStefano Zampini       if (n_vertices) {
4477ffd830a3SStefano Zampini         Mat S_VCT;
447806656605SStefano Zampini 
447906656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4480ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
448116f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
448206656605SStefano Zampini       }
4483ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
44845b782168SStefano Zampini     } else {
44855b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
448606656605SStefano Zampini     }
448716f15bc4SStefano Zampini     if (n_vertices && n_R) {
4488ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4489ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4490ffd830a3SStefano Zampini       PetscInt       n;
4491ffd830a3SStefano Zampini       PetscBool      flg_row;
449206656605SStefano Zampini 
4493ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4494af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4495ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4496ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4497ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4498ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4499ffd830a3SStefano Zampini         PetscInt j;
4500ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4501ffd830a3SStefano Zampini       }
4502ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4503ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4504ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
450506656605SStefano Zampini     }
450606656605SStefano Zampini 
4507ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4508abc8f43dSstefano_zampini     if (n_vertices) {
4509ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4510ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4511ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4512ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
451306656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
451406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
451506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
451606656605SStefano Zampini       }
4517ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4518abc8f43dSstefano_zampini     }
45195b782168SStefano Zampini     if (B_C) {
4520ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4521ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4522ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4523ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4524ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4525ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4526ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
452706656605SStefano Zampini       }
4528ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
45295b782168SStefano Zampini     }
453006656605SStefano Zampini     /* coarse basis functions */
453106656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
453206656605SStefano Zampini       PetscScalar *y;
453306656605SStefano Zampini 
4534ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
453506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
453606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
453706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
453806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
453906656605SStefano Zampini       if (i<n_vertices) {
454006656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
454106656605SStefano Zampini       }
454206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
454306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
454406656605SStefano Zampini 
454506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
454606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
454706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
454806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
455006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
455106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
455206656605SStefano Zampini       }
455306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
455406656605SStefano Zampini     }
4555ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4556ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
455706656605SStefano Zampini   }
4558a6e023c1Sstefano_zampini 
4559d62866d3SStefano Zampini   /* free memory */
456088ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
456106656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
456206656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
456306656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
456406656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4565d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4566d62866d3SStefano Zampini   if (n_vertices) {
4567d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4568d62866d3SStefano Zampini   }
4569d62866d3SStefano Zampini   if (n_constraints) {
4570d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4571d62866d3SStefano Zampini   }
457288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
457388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
457488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4575d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
457688ebb749SStefano Zampini     Mat         coarse_sub_mat;
457725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
457888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
457988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
458088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
45818bec7fa6SStefano Zampini     Mat         C_B,CPHI;
45828bec7fa6SStefano Zampini     IS          is_dummy;
45838bec7fa6SStefano Zampini     Vec         mones;
458488ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
458588ebb749SStefano Zampini     PetscReal   real_value;
458688ebb749SStefano Zampini 
4587a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4588a3df083aSStefano Zampini       Mat A;
4589a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
45907dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
45917dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
45927dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
45937dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4594a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4595a3df083aSStefano Zampini     } else {
459688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
459788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
459888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
459988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4600a3df083aSStefano Zampini     }
460188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
460288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4603ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
460488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
460588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
460688ebb749SStefano Zampini     }
460788ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
460888ebb749SStefano Zampini 
460925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46103301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
461125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4612ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
461388ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
461488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
461588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
461688ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
461788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
461888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
461988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
462088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
462188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
462288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
462388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
462488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
462588ebb749SStefano Zampini     } else {
462688ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
462788ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
462888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
462988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
463088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
463188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
463288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
463388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
463488ebb749SStefano Zampini     }
463588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
463688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
463788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4638511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
46394f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4640fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4641d12edf2fSStefano Zampini       PetscScalar *data,*data2;
46424f1b2e48SStefano Zampini       PetscInt    j;
4643d12edf2fSStefano Zampini 
46444f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
46457dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4646d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
464786c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4648d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4649d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
46504f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
46514f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4652d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
46534f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
46544f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
46554f1b2e48SStefano Zampini         }
4656d12edf2fSStefano Zampini       }
4657d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4658d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4659d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4660d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4661d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4662d12edf2fSStefano Zampini     }
4663d12edf2fSStefano Zampini #if 0
4664d12edf2fSStefano Zampini   {
4665d12edf2fSStefano Zampini     PetscViewer viewer;
4666d12edf2fSStefano Zampini     char filename[256];
4667ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4668d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4669a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4670ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4671ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4672ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4673d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4674a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4675ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4676ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
467772b8c272SStefano Zampini     }
4678ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4679ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4680ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4681ffd830a3SStefano Zampini     }
4682ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4683ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4684ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4685ffd830a3SStefano Zampini     }
468672b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4687ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4688ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4689ffd830a3SStefano Zampini     }
4690fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4691fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4692fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4693fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4694fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4695fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4696fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4697fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4698fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4699fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4700d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4701d12edf2fSStefano Zampini   }
4702d12edf2fSStefano Zampini #endif
470381d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
47048bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
47051575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
470606656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
47078bec7fa6SStefano Zampini 
47088bec7fa6SStefano Zampini     /* check constraints */
4709a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
47107dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
47114f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
47128bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4713a00504b5SStefano Zampini     } else {
4714a00504b5SStefano Zampini       PetscScalar *data;
4715a00504b5SStefano Zampini       Mat         tmat;
4716a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4717a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4718a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4719a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4720a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4721a00504b5SStefano Zampini     }
47228bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
47238bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
47248bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
47258bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4726bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4727ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4728bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4729bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4730bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4731bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4732bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
473388ebb749SStefano Zampini     }
47348bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
47358bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
47368bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
47378bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
473825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
473988ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
474088ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
474188ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
474288ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
474388ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
474488ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
474588ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
474688ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
474788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
474888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4749ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
475088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
475188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
475288ebb749SStefano Zampini     }
475388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
475488ebb749SStefano Zampini   }
47558629588bSStefano Zampini   /* get back data */
47568629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
475743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
475888ebb749SStefano Zampini   PetscFunctionReturn(0);
475988ebb749SStefano Zampini }
476088ebb749SStefano Zampini 
47617dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4762aa0d41d4SStefano Zampini {
4763d65f70fdSStefano Zampini   Mat            *work_mat;
4764d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4765d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4766c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4767aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4768aa0d41d4SStefano Zampini 
4769aa0d41d4SStefano Zampini   PetscFunctionBegin;
4770d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4771d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4772d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4773d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4774aa0d41d4SStefano Zampini 
4775d65f70fdSStefano Zampini   if (!rsorted) {
4776906d46d4SStefano Zampini     const PetscInt *idxs;
4777906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4778aa0d41d4SStefano Zampini 
4779d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4780d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4781d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4782d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4783aa0d41d4SStefano Zampini     }
4784d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4785d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4786d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4787d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4788aa0d41d4SStefano Zampini     }
4789d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4790d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4791d65f70fdSStefano Zampini   } else {
4792d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4793d65f70fdSStefano Zampini     isrow_s = isrow;
4794aa0d41d4SStefano Zampini   }
4795906d46d4SStefano Zampini 
4796d65f70fdSStefano Zampini   if (!csorted) {
4797d65f70fdSStefano Zampini     if (isrow == iscol) {
4798d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4799d65f70fdSStefano Zampini       iscol_s = isrow_s;
4800d65f70fdSStefano Zampini     } else {
4801d65f70fdSStefano Zampini       const PetscInt *idxs;
4802d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4803906d46d4SStefano Zampini 
4804d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4805d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4806d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4807d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4808d65f70fdSStefano Zampini       }
4809d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4810d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4811d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4812d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4813d65f70fdSStefano Zampini       }
4814d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4815d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4816d65f70fdSStefano Zampini     }
4817d65f70fdSStefano Zampini   } else {
4818d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4819d65f70fdSStefano Zampini     iscol_s = iscol;
4820d65f70fdSStefano Zampini   }
4821d65f70fdSStefano Zampini 
48227dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4823d65f70fdSStefano Zampini 
4824d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4825906d46d4SStefano Zampini     Mat      new_mat;
4826d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4827906d46d4SStefano Zampini 
4828d65f70fdSStefano Zampini     if (!rsorted) {
4829d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4830d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4831d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4832d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4833906d46d4SStefano Zampini       }
4834d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4835d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4836d65f70fdSStefano Zampini     } else {
4837d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4838906d46d4SStefano Zampini     }
4839d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4840d65f70fdSStefano Zampini 
4841d65f70fdSStefano Zampini     if (!csorted) {
4842d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4843d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4844d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4845d65f70fdSStefano Zampini       } else {
4846d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4847f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4848d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4849d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4850d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4851d65f70fdSStefano Zampini         }
4852d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4853d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4854d65f70fdSStefano Zampini       }
4855d65f70fdSStefano Zampini     } else {
4856d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4857d65f70fdSStefano Zampini     }
4858d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4859d65f70fdSStefano Zampini 
4860d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4861d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4862d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4863d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4864d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4865d65f70fdSStefano Zampini   }
4866d65f70fdSStefano Zampini 
4867d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4868d65f70fdSStefano Zampini   *B = work_mat[0];
4869d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4870d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4871d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4872d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4873d65f70fdSStefano Zampini }
4874d65f70fdSStefano Zampini 
48755e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4876aa0d41d4SStefano Zampini {
4877aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
48785e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4879022d8d2bSstefano_zampini   Mat            new_mat,lA;
48805e8657edSStefano Zampini   IS             is_local,is_global;
4881d65f70fdSStefano Zampini   PetscInt       local_size;
4882d65f70fdSStefano Zampini   PetscBool      isseqaij;
4883aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4884aa0d41d4SStefano Zampini 
4885aa0d41d4SStefano Zampini   PetscFunctionBegin;
4886aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
48875e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
48885e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4889b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4890aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
48917dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4892aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4893906d46d4SStefano Zampini 
4894906d46d4SStefano Zampini   /* check */
4895906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4896906d46d4SStefano Zampini     Vec       x,x_change;
4897906d46d4SStefano Zampini     PetscReal error;
4898906d46d4SStefano Zampini 
48995e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4900906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
49015e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4902e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4903e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4904d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
490588428137SStefano Zampini     if (!pcbddc->change_interior) {
490688428137SStefano Zampini       const PetscScalar *x,*y,*v;
490788428137SStefano Zampini       PetscReal         lerror = 0.;
490888428137SStefano Zampini       PetscInt          i;
490988428137SStefano Zampini 
491088428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
491188428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
491288428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
491388428137SStefano Zampini       for (i=0;i<local_size;i++)
491488428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
491588428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
491688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
491788428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
491888428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
491988428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4920637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4921637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4922637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4923637e8532SStefano Zampini         } else {
4924637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4925637e8532SStefano Zampini         }
4926637e8532SStefano Zampini       }
492788428137SStefano Zampini     }
4928e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4929e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4930906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4931906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4932637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4933637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4934637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4935637e8532SStefano Zampini       } else {
4936637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4937637e8532SStefano Zampini       }
4938637e8532SStefano Zampini     }
4939906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4940906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4941906d46d4SStefano Zampini   }
4942906d46d4SStefano Zampini 
4943022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4944022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4945022d8d2bSstefano_zampini 
494622d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
49479b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
494822d5777bSStefano Zampini   if (isseqaij) {
4949a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4950a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4951022d8d2bSstefano_zampini     if (lA) {
4952022d8d2bSstefano_zampini       Mat work;
4953022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4954022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4955022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4956022d8d2bSstefano_zampini     }
4957aa0d41d4SStefano Zampini   } else {
4958a00504b5SStefano Zampini     Mat work_mat;
49591cf9b237SStefano Zampini 
4960a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4961aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4962a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
49631d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4964022d8d2bSstefano_zampini     if (lA) {
4965022d8d2bSstefano_zampini       Mat work;
4966022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4967022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4968022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4969022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4970022d8d2bSstefano_zampini     }
4971aa0d41d4SStefano Zampini   }
49723301b35fSStefano Zampini   if (matis->A->symmetric_set) {
49733301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4974e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
49753301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4976e496cd5dSStefano Zampini #endif
49773301b35fSStefano Zampini   }
4978d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4979aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4980aa0d41d4SStefano Zampini }
4981aa0d41d4SStefano Zampini 
49828ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4983a64d13efSStefano Zampini {
4984a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4985a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4986d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
498753892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
49883a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
49893a50541eSStefano Zampini   PetscInt        vbs,bs;
49906816873aSStefano Zampini   PetscBT         bitmask=NULL;
4991a64d13efSStefano Zampini   PetscErrorCode  ierr;
4992a64d13efSStefano Zampini 
4993a64d13efSStefano Zampini   PetscFunctionBegin;
4994b23d619eSStefano Zampini   /*
4995b23d619eSStefano Zampini     No need to setup local scatters if
4996b23d619eSStefano Zampini       - primal space is unchanged
4997b23d619eSStefano Zampini         AND
4998b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4999b23d619eSStefano Zampini         AND
5000b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5001b23d619eSStefano Zampini   */
5002b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5003f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5004f4ddd8eeSStefano Zampini   }
5005f4ddd8eeSStefano Zampini   /* destroy old objects */
5006f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
5007f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
5008f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
5009a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5010b371cd4fSStefano Zampini   n_B = pcis->n_B;
5011b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5012b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
50133a50541eSStefano Zampini 
5014a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
50156816873aSStefano Zampini 
501653892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5017b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
5018854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
5019a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
5020a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
50210e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
5022a64d13efSStefano Zampini     }
5023a64d13efSStefano Zampini 
5024a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
50254641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
50266816873aSStefano Zampini         idx_R_local[n_R++] = i;
5027a64d13efSStefano Zampini       }
5028a64d13efSStefano Zampini     }
5029df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5030df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
50316816873aSStefano Zampini 
5032df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5033df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
50346816873aSStefano Zampini   }
50353a50541eSStefano Zampini 
50363a50541eSStefano Zampini   /* Block code */
50373a50541eSStefano Zampini   vbs = 1;
50383a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
50393a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
50403a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
50413a50541eSStefano Zampini     PetscInt  *vary;
5042b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5043785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
50443a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
5045d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5046d3df7717SStefano 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 */
50470e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5048d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
50493a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
50503a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
50513a50541eSStefano Zampini           break;
50523a50541eSStefano Zampini         }
50533a50541eSStefano Zampini       }
5054d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5055d3df7717SStefano Zampini     } else {
5056d3df7717SStefano Zampini       /* Verify directly the R set */
5057d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5058d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5059d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5060d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5061d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5062d3df7717SStefano Zampini             break;
5063d3df7717SStefano Zampini           }
5064d3df7717SStefano Zampini         }
5065d3df7717SStefano Zampini       }
5066d3df7717SStefano Zampini     }
50673a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
50683a50541eSStefano Zampini       vbs = bs;
50693a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
50703a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
50713a50541eSStefano Zampini       }
50723a50541eSStefano Zampini     }
50733a50541eSStefano Zampini   }
50743a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5075b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5076df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
507753892102SStefano Zampini 
5078df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5079df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
508053892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5081df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
508253892102SStefano Zampini   } else {
50833a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
508453892102SStefano Zampini   }
5085a64d13efSStefano Zampini 
5086a64d13efSStefano Zampini   /* print some info if requested */
5087a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5088a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5089a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50901575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5091a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
5092a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
50934f1b2e48SStefano 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);
5094a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5095a64d13efSStefano Zampini   }
5096a64d13efSStefano Zampini 
5097a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5098b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
50996816873aSStefano Zampini     IS       is_aux1,is_aux2;
51006816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
51016816873aSStefano Zampini 
51023a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5103854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5104854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5105a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
51064641a718SStefano Zampini     for (i=0; i<n_D; i++) {
51074641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
51084641a718SStefano Zampini     }
5109a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5110a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
51114641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
51124641a718SStefano Zampini         aux_array1[j++] = i;
5113a64d13efSStefano Zampini       }
5114a64d13efSStefano Zampini     }
5115a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5116a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5117a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
51184641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
51194641a718SStefano Zampini         aux_array2[j++] = i;
5120a64d13efSStefano Zampini       }
5121a64d13efSStefano Zampini     }
5122a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5123a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
5124a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5125a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5126a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5127a64d13efSStefano Zampini 
51288eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5129785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5130a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
51314641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
51324641a718SStefano Zampini           aux_array1[j++] = i;
5133a64d13efSStefano Zampini         }
5134a64d13efSStefano Zampini       }
5135a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5136a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5137a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5138a64d13efSStefano Zampini     }
51394641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
51403a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5141d62866d3SStefano Zampini   } else {
5142df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
51436816873aSStefano Zampini     IS                 tis;
51446816873aSStefano Zampini     PetscInt           schur_size;
51456816873aSStefano Zampini 
5146df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
51476816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
5148df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
51496816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
51506816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
51516816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
51526816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
51536816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5154d62866d3SStefano Zampini     }
5155d62866d3SStefano Zampini   }
5156a64d13efSStefano Zampini   PetscFunctionReturn(0);
5157a64d13efSStefano Zampini }
5158a64d13efSStefano Zampini 
5159304d26faSStefano Zampini 
5160684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5161304d26faSStefano Zampini {
5162304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5163304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5164304d26faSStefano Zampini   PC             pc_temp;
5165304d26faSStefano Zampini   Mat            A_RR;
5166f4ddd8eeSStefano Zampini   MatReuse       reuse;
5167304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5168304d26faSStefano Zampini   PetscReal      value;
516904708bb6SStefano Zampini   PetscInt       n_D,n_R;
517035529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
5171304d26faSStefano Zampini   PetscErrorCode ierr;
5172e604994aSStefano Zampini   /* prefixes stuff */
5173312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5174e604994aSStefano Zampini   size_t         len;
5175304d26faSStefano Zampini 
5176304d26faSStefano Zampini   PetscFunctionBegin;
517743371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5178e604994aSStefano Zampini   /* compute prefixes */
5179e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5180e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5181e604994aSStefano Zampini   if (!pcbddc->current_level) {
5182a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5183a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5184a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5185a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5186e604994aSStefano Zampini   } else {
518735529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5188e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5189e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5190312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5191312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5192a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
519334d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
519434d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5195a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5196a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5197a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5198a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5199e604994aSStefano Zampini   }
5200e604994aSStefano Zampini 
5201304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5202684f6988SStefano Zampini   if (dirichlet) {
5203d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5204450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
52059a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
5206450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5207a3df083aSStefano Zampini         Mat    A_IIn;
5208a3df083aSStefano Zampini 
5209a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5210a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5211a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5212a3df083aSStefano Zampini       }
5213450f8f5eSStefano Zampini     }
52143301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
52153301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
5216964fefecSStefano Zampini     }
5217ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5218964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
5219304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
5220cd18cfedSStefano Zampini       void (*f)(void) = 0;
5221cd18cfedSStefano Zampini 
5222304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5223304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5224304d26faSStefano Zampini       /* default */
5225304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5226e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
52279577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5228304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
52299577ea80SStefano Zampini       if (issbaij) {
52309577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
52319577ea80SStefano Zampini       } else {
5232304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
52339577ea80SStefano Zampini       }
5234*399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure);CHKERRQ(ierr);
5235304d26faSStefano Zampini       /* Allow user's customization */
5236304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5237cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5238cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5239cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5240cd18cfedSStefano Zampini         const PetscInt *idxs;
5241cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5242cd18cfedSStefano Zampini 
5243cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5244cd18cfedSStefano Zampini         ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5245cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5246cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5247cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5248cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5249cd18cfedSStefano Zampini           }
5250cd18cfedSStefano Zampini         }
5251cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5252cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5253cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5254cd18cfedSStefano Zampini       }
5255304d26faSStefano Zampini     }
5256d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5257b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5258df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5259d62866d3SStefano Zampini 
5260df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5261d5574798SStefano Zampini     }
5262304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5263304d26faSStefano Zampini     if (!n_D) {
5264304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5265304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5266304d26faSStefano Zampini     }
5267304d26faSStefano Zampini     /* set ksp_D into pcis data */
5268304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5269304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5270304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5271684f6988SStefano Zampini   }
5272304d26faSStefano Zampini 
5273304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5274684f6988SStefano Zampini   A_RR = 0;
5275684f6988SStefano Zampini   if (neumann) {
5276d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
527704708bb6SStefano Zampini     PetscInt        ibs,mbs;
52780aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
527904708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
52800aa714b2SStefano Zampini 
52810aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
52820aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
52830aa714b2SStefano Zampini       IS iP;
52840aa714b2SStefano Zampini 
52850aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
52860aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
52870aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
52880aa714b2SStefano Zampini     }
5289f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
52908ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5291f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5292f4ddd8eeSStefano Zampini       PetscInt nn_R;
529381d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5294f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5295f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5296f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5297f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5298f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5299f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5300f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5301727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5302f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5303f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5304f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5305f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5306f4ddd8eeSStefano Zampini         }
5307f4ddd8eeSStefano Zampini       }
5308f4ddd8eeSStefano Zampini       /* last check */
5309d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5310f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5311f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5312f4ddd8eeSStefano Zampini       }
5313f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5314f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5315f4ddd8eeSStefano Zampini     }
5316a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5317af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5318af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
531904708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
532004708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
532104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
532204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
532304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5324af732b37SStefano Zampini       } else {
5325511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
53266816873aSStefano Zampini       }
532704708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
532804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
532904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
533004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
533104708bb6SStefano Zampini       } else {
5332511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
533304708bb6SStefano Zampini       }
533404708bb6SStefano Zampini     }
5335a00504b5SStefano Zampini     /* extract A_RR */
53360aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5337a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5338a00504b5SStefano Zampini 
5339a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
534016e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5341a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
534216e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
534316e386b8SStefano Zampini         } else {
53447dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5345a00504b5SStefano Zampini         }
5346a00504b5SStefano Zampini       } else {
5347a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5348a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5349a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5350a00504b5SStefano Zampini       }
5351a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
53527dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
535316e386b8SStefano Zampini     }
53543301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
53553301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
53566816873aSStefano Zampini     }
5357f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5358cd18cfedSStefano Zampini       void (*f)(void) = 0;
5359cd18cfedSStefano Zampini 
5360304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5361304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5362304d26faSStefano Zampini       /* default */
5363304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5364e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5365304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
53669577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
53679577ea80SStefano Zampini       if (issbaij) {
53689577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
53699577ea80SStefano Zampini       } else {
5370304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
53719577ea80SStefano Zampini       }
5372*399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure);CHKERRQ(ierr);
5373304d26faSStefano Zampini       /* Allow user's customization */
5374304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5375cd18cfedSStefano Zampini       ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
5376cd18cfedSStefano Zampini       if (f && pcbddc->mat_graph->cloc) {
5377cd18cfedSStefano Zampini         PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5378cd18cfedSStefano Zampini         const PetscInt *idxs;
5379cd18cfedSStefano Zampini         PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5380cd18cfedSStefano Zampini 
5381cd18cfedSStefano Zampini         ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5382cd18cfedSStefano Zampini         ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5383cd18cfedSStefano Zampini         ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5384cd18cfedSStefano Zampini         for (i=0;i<nl;i++) {
5385cd18cfedSStefano Zampini           for (d=0;d<cdim;d++) {
5386cd18cfedSStefano Zampini             scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5387cd18cfedSStefano Zampini           }
5388cd18cfedSStefano Zampini         }
5389cd18cfedSStefano Zampini         ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5390cd18cfedSStefano Zampini         ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5391cd18cfedSStefano Zampini         ierr = PetscFree(scoords);CHKERRQ(ierr);
5392cd18cfedSStefano Zampini       }
5393304d26faSStefano Zampini     }
5394304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5395304d26faSStefano Zampini     if (!n_R) {
5396304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5397304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5398304d26faSStefano Zampini     }
53995cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5400df4d28bfSStefano Zampini     /* Reuse solver if it is present */
54010aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5402df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5403d62866d3SStefano Zampini 
5404df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5405d62866d3SStefano Zampini     }
5406684f6988SStefano Zampini   }
5407304d26faSStefano Zampini 
5408684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5409684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54101575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5411684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5412684f6988SStefano Zampini   }
5413c7017625SStefano Zampini 
5414c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
541535529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5416c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5417c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5418c7017625SStefano Zampini   }
5419c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
542035529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5421c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5422c7017625SStefano Zampini   }
5423c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
542435529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5425c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5426c7017625SStefano Zampini   }
5427c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5428c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5429684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
54300fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
54310fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
54320fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
54330fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
54340fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5435e604994aSStefano 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);
543635529e7bSStefano Zampini       if (check_corr) {
5437c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5438c7017625SStefano Zampini       }
5439304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5440304d26faSStefano Zampini     }
5441684f6988SStefano Zampini     if (neumann) { /* Neumann */
54420fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
54430fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
54440fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
54450fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
54460fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5447e604994aSStefano 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);
544835529e7bSStefano Zampini       if (check_corr) {
5449c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5450c7017625SStefano Zampini       }
5451304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5452304d26faSStefano Zampini     }
5453684f6988SStefano Zampini   }
54545cbda25cSStefano Zampini   /* free Neumann problem's matrix */
54555cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
545643371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5457304d26faSStefano Zampini   PetscFunctionReturn(0);
5458304d26faSStefano Zampini }
5459304d26faSStefano Zampini 
546080677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5461674ae819SStefano Zampini {
5462674ae819SStefano Zampini   PetscErrorCode  ierr;
5463674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5464be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5465b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5466674ae819SStefano Zampini 
5467674ae819SStefano Zampini   PetscFunctionBegin;
5468b334f244SStefano Zampini   if (!reuse_solver) {
546980677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
547020c7b377SStefano Zampini   }
547180677318SStefano Zampini   if (!pcbddc->switch_static) {
547280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
547380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
547480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
547520c7b377SStefano Zampini     }
5476b334f244SStefano Zampini     if (!reuse_solver) {
547780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
547880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
547920c7b377SStefano Zampini     } else {
5480df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5481be83ff47SStefano Zampini 
5482df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5483df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
548420c7b377SStefano Zampini     }
5485be83ff47SStefano Zampini   } else {
548680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
548780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
548880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
548980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
549080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
549180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
549280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
549380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
549480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5495674ae819SStefano Zampini     }
5496674ae819SStefano Zampini   }
5497b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
549880677318SStefano Zampini     if (applytranspose) {
549980677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
550080677318SStefano Zampini     } else {
550180677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
550280677318SStefano Zampini     }
5503be83ff47SStefano Zampini   } else {
5504df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5505be83ff47SStefano Zampini 
5506be83ff47SStefano Zampini     if (applytranspose) {
5507df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5508be83ff47SStefano Zampini     } else {
5509df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5510be83ff47SStefano Zampini     }
5511be83ff47SStefano Zampini   }
551280677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
551380677318SStefano Zampini   if (!pcbddc->switch_static) {
5514b334f244SStefano Zampini     if (!reuse_solver) {
551580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
551680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5517be83ff47SStefano Zampini     } else {
5518df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5519be83ff47SStefano Zampini 
5520df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5521df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5522be83ff47SStefano Zampini     }
552380677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
552480677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
552580677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
552680677318SStefano Zampini     }
552780677318SStefano Zampini   } else {
552880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
552980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
553380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
553480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
553580677318SStefano Zampini     }
553680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
553980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5540674ae819SStefano Zampini   }
5541674ae819SStefano Zampini   PetscFunctionReturn(0);
5542674ae819SStefano Zampini }
5543674ae819SStefano Zampini 
5544dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5545dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5546674ae819SStefano Zampini {
5547674ae819SStefano Zampini   PetscErrorCode ierr;
5548674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5549674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5550674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5551674ae819SStefano Zampini 
5552674ae819SStefano Zampini   PetscFunctionBegin;
5553dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
55544fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5555dc359a40SStefano Zampini     if (applytranspose) {
5556674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
55578eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5558dc359a40SStefano Zampini     } else {
5559674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5560674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
556115aaf578SStefano Zampini     }
55624fee134fSStefano Zampini   } else {
55634fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
55644fee134fSStefano Zampini   }
5565efc2fbd9SStefano Zampini 
5566efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
55674f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5568efc2fbd9SStefano Zampini     PetscScalar *array;
55694f1b2e48SStefano Zampini     PetscInt    j;
5570efc2fbd9SStefano Zampini 
5571efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
55724f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5573efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5574efc2fbd9SStefano Zampini   }
5575efc2fbd9SStefano Zampini 
557612edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
557712edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
557812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
557912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
558012edc857SStefano Zampini 
55819f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
558212edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
558351694757SStefano Zampini     Mat          coarse_mat;
5584964fefecSStefano Zampini     Vec          rhs,sol;
558551694757SStefano Zampini     MatNullSpace nullsp;
558627b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5587964fefecSStefano Zampini 
558827b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
558927b6a85dSStefano Zampini       PC        coarse_pc;
559027b6a85dSStefano Zampini 
559127b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
559227b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
559327b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
559427b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
559527b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
559627b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
55973bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
559827b6a85dSStefano Zampini       }
559927b6a85dSStefano Zampini     }
5600964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5601964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
560251694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
560351694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
560451694757SStefano Zampini     if (nullsp) {
560551694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
560651694757SStefano Zampini     }
560712edc857SStefano Zampini     if (applytranspose) {
56089a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5609964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
56102701bc32SStefano Zampini     } else {
56111f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
56122701bc32SStefano Zampini         PC        coarse_pc;
56132701bc32SStefano Zampini 
56142701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
56152701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
56163e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
56172701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
561812edc857SStefano Zampini       } else {
5619964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
562012edc857SStefano Zampini       }
56212701bc32SStefano Zampini     }
56221d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
562327b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
562427b6a85dSStefano Zampini       PC        coarse_pc;
562527b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
562627b6a85dSStefano Zampini 
562727b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
562827b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
562927b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
56303bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
563127b6a85dSStefano Zampini     }
563251694757SStefano Zampini     if (nullsp) {
563351694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
563451694757SStefano Zampini     }
563512edc857SStefano Zampini   }
5636674ae819SStefano Zampini 
5637674ae819SStefano Zampini   /* Local solution on R nodes */
56384fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
563980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
56409f00e9b4SStefano Zampini   }
56419f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
56429f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
564312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5644674ae819SStefano Zampini 
56454fee134fSStefano Zampini   /* Sum contributions from the two levels */
56464fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5647dc359a40SStefano Zampini     if (applytranspose) {
5648dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5649dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5650dc359a40SStefano Zampini     } else {
5651674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
56528eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5653dc359a40SStefano Zampini     }
5654efc2fbd9SStefano Zampini     /* store p0 */
56554f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5656efc2fbd9SStefano Zampini       PetscScalar *array;
56574f1b2e48SStefano Zampini       PetscInt    j;
5658efc2fbd9SStefano Zampini 
5659efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
56604f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5661efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5662efc2fbd9SStefano Zampini     }
56634fee134fSStefano Zampini   } else { /* expand the coarse solution */
56644fee134fSStefano Zampini     if (applytranspose) {
56654fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
56664fee134fSStefano Zampini     } else {
56674fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
56684fee134fSStefano Zampini     }
56694fee134fSStefano Zampini   }
5670674ae819SStefano Zampini   PetscFunctionReturn(0);
5671674ae819SStefano Zampini }
5672674ae819SStefano Zampini 
567312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5674674ae819SStefano Zampini {
5675674ae819SStefano Zampini   PetscErrorCode ierr;
5676674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
567758da7f69SStefano Zampini   PetscScalar    *array;
567812edc857SStefano Zampini   Vec            from,to;
5679674ae819SStefano Zampini 
5680674ae819SStefano Zampini   PetscFunctionBegin;
568112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
568212edc857SStefano Zampini     from = pcbddc->coarse_vec;
568312edc857SStefano Zampini     to = pcbddc->vec1_P;
568412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
568512edc857SStefano Zampini       Vec tvec;
568658da7f69SStefano Zampini 
568758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
568858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
568912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
569058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
569158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
569258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
569312edc857SStefano Zampini     }
569412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
569512edc857SStefano Zampini     from = pcbddc->vec1_P;
569612edc857SStefano Zampini     to = pcbddc->coarse_vec;
569712edc857SStefano Zampini   }
569812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5699674ae819SStefano Zampini   PetscFunctionReturn(0);
5700674ae819SStefano Zampini }
5701674ae819SStefano Zampini 
570212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5703674ae819SStefano Zampini {
5704674ae819SStefano Zampini   PetscErrorCode ierr;
5705674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
570658da7f69SStefano Zampini   PetscScalar    *array;
570712edc857SStefano Zampini   Vec            from,to;
5708674ae819SStefano Zampini 
5709674ae819SStefano Zampini   PetscFunctionBegin;
571012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
571112edc857SStefano Zampini     from = pcbddc->coarse_vec;
571212edc857SStefano Zampini     to = pcbddc->vec1_P;
571312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
571412edc857SStefano Zampini     from = pcbddc->vec1_P;
571512edc857SStefano Zampini     to = pcbddc->coarse_vec;
571612edc857SStefano Zampini   }
571712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
571812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
571912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
572012edc857SStefano Zampini       Vec tvec;
572158da7f69SStefano Zampini 
572212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
572358da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
572458da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
572558da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
572658da7f69SStefano Zampini     }
572758da7f69SStefano Zampini   } else {
572858da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
572958da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
573012edc857SStefano Zampini     }
573112edc857SStefano Zampini   }
5732674ae819SStefano Zampini   PetscFunctionReturn(0);
5733674ae819SStefano Zampini }
5734674ae819SStefano Zampini 
5735984c4197SStefano Zampini /* uncomment for testing purposes */
5736984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5737674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5738674ae819SStefano Zampini {
5739674ae819SStefano Zampini   PetscErrorCode    ierr;
5740674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5741674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5742674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5743984c4197SStefano Zampini   /* one and zero */
5744984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5745984c4197SStefano Zampini   /* space to store constraints and their local indices */
57469162d606SStefano Zampini   PetscScalar       *constraints_data;
57479162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
57489162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
57499162d606SStefano Zampini   PetscInt          *constraints_n;
5750984c4197SStefano Zampini   /* iterators */
5751b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5752984c4197SStefano Zampini   /* BLAS integers */
5753e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5754e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5755c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5756727cdba6SStefano Zampini   /* reuse */
57570e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
57580e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5759984c4197SStefano Zampini   /* change of basis */
5760b3d85658SStefano Zampini   PetscBool         qr_needed;
57619162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5762984c4197SStefano Zampini   /* auxiliary stuff */
576364efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
57648a0068c3SStefano Zampini   PetscInt          ncc;
5765984c4197SStefano Zampini   /* some quantities */
576645a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5767a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
576857715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
5769984c4197SStefano Zampini 
5770674ae819SStefano Zampini   PetscFunctionBegin;
577157715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
57728e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
57738e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57748e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
577516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5776088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5777088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
57780e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
57790e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
57800e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
57810e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
57820e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5783088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5784cf5a6209SStefano Zampini 
5785cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
57869162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5787cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5788cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5789cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5790cf5a6209SStefano Zampini     PetscScalar  *array;
5791cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5792cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5793674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5794b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5795674ae819SStefano Zampini     PetscScalar  *work;
5796674ae819SStefano Zampini     PetscReal    *singular_vals;
5797674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5798674ae819SStefano Zampini     PetscReal    *rwork;
5799674ae819SStefano Zampini #endif
5800674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5801674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5802674ae819SStefano Zampini #else
5803964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5804964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5805674ae819SStefano Zampini #endif
5806674ae819SStefano Zampini 
5807674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5808d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5809e4d548c7SStefano Zampini     /* print some info */
58105c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5811e4d548c7SStefano Zampini       PetscInt nv;
5812e4d548c7SStefano Zampini 
5813c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5814e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5815e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5816e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5817e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5818e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5819e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5820e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5821e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5822e4d548c7SStefano Zampini     }
5823e4d548c7SStefano Zampini 
5824d06fc5fdSStefano Zampini     /* free unneeded index sets */
5825d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5826d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5827674ae819SStefano Zampini     }
5828d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5829d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5830d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5831d06fc5fdSStefano Zampini       }
5832d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5833d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5834d06fc5fdSStefano Zampini     }
5835d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5836d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5837d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5838d06fc5fdSStefano Zampini       }
5839d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5840d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5841d06fc5fdSStefano Zampini     }
584270022509SStefano Zampini 
5843674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5844674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5845674ae819SStefano Zampini     if (nearnullsp) {
5846674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5847f4ddd8eeSStefano Zampini       /* remove any stored info */
5848f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5849f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5850f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5851f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5852f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5853473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5854f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5855f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5856f4ddd8eeSStefano Zampini       }
5857984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5858984c4197SStefano Zampini       nnsp_size = 0;
5859674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5860674ae819SStefano Zampini     }
5861984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5862984c4197SStefano Zampini     max_constraints = nnsp_size;
5863984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5864984c4197SStefano Zampini 
5865674ae819SStefano Zampini     /*
5866674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
58679162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
58689162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
58699162d606SStefano Zampini          There can be multiple constraints per connected component
5870674ae819SStefano Zampini                                                                                                                                                            */
5871674ae819SStefano Zampini     n_vertices = 0;
5872674ae819SStefano Zampini     if (ISForVertices) {
5873674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5874674ae819SStefano Zampini     }
58759162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
58769162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
58779162d606SStefano Zampini 
58789162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
58799162d606SStefano Zampini     total_counts *= max_constraints;
5880674ae819SStefano Zampini     total_counts += n_vertices;
58814641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
58829162d606SStefano Zampini 
5883674ae819SStefano Zampini     total_counts = 0;
5884674ae819SStefano Zampini     max_size_of_constraint = 0;
5885674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
58869162d606SStefano Zampini       IS used_is;
5887674ae819SStefano Zampini       if (i<n_ISForEdges) {
58889162d606SStefano Zampini         used_is = ISForEdges[i];
5889674ae819SStefano Zampini       } else {
58909162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5891674ae819SStefano Zampini       }
58929162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5893674ae819SStefano Zampini       total_counts += j;
5894674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5895674ae819SStefano Zampini     }
58969162d606SStefano 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);
58979162d606SStefano Zampini 
5898984c4197SStefano Zampini     /* get local part of global near null space vectors */
5899785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5900984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5901984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5902e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5903e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5904984c4197SStefano Zampini     }
5905674ae819SStefano Zampini 
5906242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5907242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5908a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5909242a89d7SStefano Zampini 
5910984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5911a773dcb8SStefano Zampini     if (!skip_lapack) {
5912674ae819SStefano Zampini       PetscScalar temp_work;
5913911cabfeSStefano Zampini 
5914674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5915984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5916785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5917785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5918785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5919674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5920785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5921674ae819SStefano Zampini #endif
5922674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5923c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5924c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5925674ae819SStefano Zampini       lwork = -1;
5926674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5927674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5928c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5929674ae819SStefano Zampini #else
5930c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5931674ae819SStefano Zampini #endif
5932674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5933984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5934674ae819SStefano Zampini #else /* on missing GESVD */
5935674ae819SStefano Zampini       /* SVD */
5936674ae819SStefano Zampini       PetscInt max_n,min_n;
5937674ae819SStefano Zampini       max_n = max_size_of_constraint;
5938984c4197SStefano Zampini       min_n = max_constraints;
5939984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5940674ae819SStefano Zampini         min_n = max_size_of_constraint;
5941984c4197SStefano Zampini         max_n = max_constraints;
5942674ae819SStefano Zampini       }
5943785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5944674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5945785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5946674ae819SStefano Zampini #endif
5947674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5948674ae819SStefano Zampini       lwork = -1;
5949e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5950e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5951b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5952674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5953674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
59549162d606SStefano 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));
5955674ae819SStefano Zampini #else
59569162d606SStefano 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));
5957674ae819SStefano Zampini #endif
5958674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5959984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5960984c4197SStefano Zampini #endif /* on missing GESVD */
5961674ae819SStefano Zampini       /* Allocate optimal workspace */
5962674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5963854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5964674ae819SStefano Zampini     }
5965674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5966674ae819SStefano Zampini     total_counts = 0;
59679162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
59689162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5969674ae819SStefano Zampini     /* vertices */
59709162d606SStefano Zampini     if (n_vertices) {
5971674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
59729162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5973674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
59749162d606SStefano Zampini         constraints_n[total_counts] = 1;
59759162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
59769162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
59779162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5978674ae819SStefano Zampini         total_counts++;
5979674ae819SStefano Zampini       }
5980674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5981674ae819SStefano Zampini       n_vertices = total_counts;
5982674ae819SStefano Zampini     }
5983984c4197SStefano Zampini 
5984674ae819SStefano Zampini     /* edges and faces */
59859162d606SStefano Zampini     total_counts_cc = total_counts;
5986911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
59879162d606SStefano Zampini       IS        used_is;
59889162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
59899162d606SStefano Zampini 
5990911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
59919162d606SStefano Zampini         used_is = ISForEdges[ncc];
5992984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5993674ae819SStefano Zampini       } else {
59949162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5995984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5996674ae819SStefano Zampini       }
5997674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
59989162d606SStefano Zampini 
59999162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
60009162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6001984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6002984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6003674ae819SStefano Zampini       if (nnsp_has_cnst) {
60045b08dc53SStefano Zampini         PetscScalar quad_value;
60059162d606SStefano Zampini 
60069162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
60079162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
60089162d606SStefano Zampini 
6009a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6010674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6011a773dcb8SStefano Zampini         } else {
6012a773dcb8SStefano Zampini           quad_value = 1.0;
6013a773dcb8SStefano Zampini         }
6014674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
60159162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6016674ae819SStefano Zampini         }
60179162d606SStefano Zampini         temp_constraints++;
6018674ae819SStefano Zampini         total_counts++;
6019674ae819SStefano Zampini       }
6020674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6021984c4197SStefano Zampini         PetscReal real_value;
60229162d606SStefano Zampini         PetscScalar *ptr_to_data;
60239162d606SStefano Zampini 
6024984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
60259162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6026674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
60279162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6028674ae819SStefano Zampini         }
6029984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
6030984c4197SStefano Zampini         /* check if array is null on the connected component */
6031e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
60329162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
603357715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6034674ae819SStefano Zampini           temp_constraints++;
6035674ae819SStefano Zampini           total_counts++;
60369162d606SStefano Zampini           if (!idxs_copied) {
60379162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
60389162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6039674ae819SStefano Zampini           }
6040674ae819SStefano Zampini         }
60419162d606SStefano Zampini       }
60429162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
604345a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6044eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6045a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
60469162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
60479162d606SStefano Zampini 
60489162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6049a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
60509162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6051a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
60529162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6053a773dcb8SStefano Zampini         } else { /* perform SVD */
60549162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6055674ae819SStefano Zampini 
6056674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6057984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6058984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6059984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6060984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
6061984c4197SStefano Zampini                 from that computed using LAPACKgesvd
6062984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
6063984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
6064984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
6065674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
6066e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6067984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6068674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
6069674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
60709162d606SStefano 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));
6071674ae819SStefano Zampini             }
6072674ae819SStefano Zampini           }
6073e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
6074e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6075e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6076674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6077c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6078674ae819SStefano Zampini #else
6079c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6080674ae819SStefano Zampini #endif
6081674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6082984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6083984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6084674ae819SStefano Zampini           j = 0;
6085984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
6086674ae819SStefano Zampini           total_counts = total_counts-j;
608745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
6088e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
6089c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6090c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6091c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6092c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6093c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6094c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6095674ae819SStefano Zampini           if (j<temp_constraints) {
6096984c4197SStefano Zampini             PetscInt ii;
6097984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6098674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
60999162d606SStefano 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));
6100674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6101984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
6102674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
61039162d606SStefano 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];
6104674ae819SStefano Zampini               }
6105674ae819SStefano Zampini             }
6106674ae819SStefano Zampini           }
6107674ae819SStefano Zampini #else  /* on missing GESVD */
6108e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6109e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6110b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6111674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6112674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
61139162d606SStefano 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));
6114674ae819SStefano Zampini #else
61159162d606SStefano 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));
6116674ae819SStefano Zampini #endif
6117984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6118674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6119984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6120e310c8b4SStefano Zampini           k = temp_constraints;
6121e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
6122674ae819SStefano Zampini           j = 0;
6123e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
612445a1bb75SStefano Zampini           valid_constraints = k-j;
6125911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
6126984c4197SStefano Zampini #endif /* on missing GESVD */
6127674ae819SStefano Zampini         }
6128a773dcb8SStefano Zampini       }
61299162d606SStefano Zampini       /* update pointers information */
61309162d606SStefano Zampini       if (valid_constraints) {
61319162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
61329162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
61339162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
61349162d606SStefano Zampini         /* set change_of_basis flag */
613545a1bb75SStefano Zampini         if (boolforchange) {
6136b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
61379162d606SStefano Zampini         }
6138b3d85658SStefano Zampini         total_counts_cc++;
613945a1bb75SStefano Zampini       }
614045a1bb75SStefano Zampini     }
6141984c4197SStefano Zampini     /* free workspace */
61428f1c130eSStefano Zampini     if (!skip_lapack) {
6143984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6144984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6145984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6146984c4197SStefano Zampini #endif
6147984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6148984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
6149984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6150984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6151984c4197SStefano Zampini #endif
6152984c4197SStefano Zampini     }
6153984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6154984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6155984c4197SStefano Zampini     }
6156984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6157cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6158cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6159cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6160cf5a6209SStefano Zampini     }
6161cf5a6209SStefano Zampini     if (n_ISForFaces) {
6162cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6163cf5a6209SStefano Zampini     }
6164cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6165cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6166cf5a6209SStefano Zampini     }
6167cf5a6209SStefano Zampini     if (n_ISForEdges) {
6168cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6169cf5a6209SStefano Zampini     }
6170cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
617108122e43SStefano Zampini   } else {
617208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6173984c4197SStefano Zampini 
617408122e43SStefano Zampini     total_counts = 0;
617508122e43SStefano Zampini     n_vertices = 0;
6176d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6177d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
617808122e43SStefano Zampini     }
617908122e43SStefano Zampini     max_constraints = 0;
61809162d606SStefano Zampini     total_counts_cc = 0;
618108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
618208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
61839162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
618408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
618508122e43SStefano Zampini     }
61869162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
61879162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
61889162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
61899162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
619074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
61919162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
61929162d606SStefano Zampini     total_counts_cc = 0;
61939162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
61949162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
61959162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
619608122e43SStefano Zampini       }
619708122e43SStefano Zampini     }
619808122e43SStefano Zampini 
61998bec7fa6SStefano Zampini     max_size_of_constraint = 0;
62009162d606SStefano 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]);
62019162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
620208122e43SStefano Zampini     /* Change of basis */
6203b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
620408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
620508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
620608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6207b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
620808122e43SStefano Zampini         }
620908122e43SStefano Zampini       }
621008122e43SStefano Zampini     }
621108122e43SStefano Zampini   }
6212984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
62134f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
621408122e43SStefano Zampini 
62159162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
62169162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
6217eee23b56SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
6218674ae819SStefano Zampini 
6219674ae819SStefano Zampini   /* Create constraint matrix */
6220674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
622116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6222984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6223984c4197SStefano Zampini 
6224984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6225a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
6226a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
622774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6228984c4197SStefano Zampini   total_primal_vertices=0;
6229b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
62309162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
62319162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
623272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
62339162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6234b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
623564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
62369162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
62379162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6238a717540cSStefano Zampini       }
6239b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
624091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6241a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6242a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6243a717540cSStefano Zampini       }
6244fa434743SStefano Zampini     } else {
6245b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6246fa434743SStefano Zampini     }
6247a717540cSStefano Zampini   }
6248b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6249b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6250674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
625170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
62524f1b2e48SStefano 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);
62530e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
62540e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6255984c4197SStefano Zampini 
6256984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
625774d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6258785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6259984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
626074d5cdf7SStefano Zampini 
6261984c4197SStefano Zampini   j = total_primal_vertices;
626274d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6263b3d85658SStefano Zampini   cum = total_primal_vertices;
62649162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
62654641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6266b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6267b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6268b3d85658SStefano Zampini       cum++;
62699162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
627074d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
627174d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
627274d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
627374d5cdf7SStefano Zampini       }
62749162d606SStefano Zampini       j += constraints_n[i];
6275674ae819SStefano Zampini     }
6276674ae819SStefano Zampini   }
6277674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6278e1b21442SStefano Zampini   ierr = MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6279674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6280088faed8SStefano Zampini 
6281674ae819SStefano Zampini   /* set values in constraint matrix */
6282984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
62830e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6284674ae819SStefano Zampini   }
6285984c4197SStefano Zampini   total_counts = total_primal_vertices;
62869162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
62874641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
62889162d606SStefano Zampini       PetscInt *cols;
62899162d606SStefano Zampini 
62909162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
62919162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
62929162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
62939162d606SStefano Zampini         PetscInt    row = total_counts+k;
62949162d606SStefano Zampini         PetscScalar *vals;
62959162d606SStefano Zampini 
62969162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
62979162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
62989162d606SStefano Zampini       }
62999162d606SStefano Zampini       total_counts += constraints_n[i];
6300674ae819SStefano Zampini     }
6301674ae819SStefano Zampini   }
6302674ae819SStefano Zampini   /* assembling */
6303674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6304674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63053272d46bSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,NULL,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6306088faed8SStefano Zampini 
6307674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6308674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6309026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6310984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6311984c4197SStefano Zampini     /* working stuff for GEQRF */
631281d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
6313984c4197SStefano Zampini     PetscBLASInt lqr_work;
6314984c4197SStefano Zampini     /* working stuff for UNGQR */
6315984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
6316984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6317984c4197SStefano Zampini     /* working stuff for TRTRS */
6318984c4197SStefano Zampini     PetscScalar  *trs_rhs;
63193f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6320984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6321984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6322984c4197SStefano Zampini     PetscScalar  *start_vals;
6323984c4197SStefano Zampini     /* working stuff for values insertion */
63244641a718SStefano Zampini     PetscBT      is_primal;
632564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6326906d46d4SStefano Zampini     /* matrix sizes */
6327906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6328906d46d4SStefano Zampini     /* temporary change of basis */
6329906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6330cf5a6209SStefano Zampini     /* extra space for debugging */
6331cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
6332984c4197SStefano Zampini 
6333906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6334906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
633516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6336bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6337906d46d4SStefano Zampini     /* nonzeros for local mat */
6338bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
63391dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6340bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
63411dd7afcfSStefano Zampini     } else {
63421dd7afcfSStefano Zampini       const PetscInt *ii;
63431dd7afcfSStefano Zampini       PetscInt       n;
63441dd7afcfSStefano Zampini       PetscBool      flg_row;
63451dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
63461dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
63471dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
63481dd7afcfSStefano Zampini     }
63499162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6350a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
63519162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6352a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
63539162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6354a717540cSStefano Zampini         } else {
63559162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
63569162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6357a717540cSStefano Zampini         }
6358a717540cSStefano Zampini       }
6359a717540cSStefano Zampini     }
6360906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6361e1b21442SStefano Zampini     ierr = MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6362bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
63631dd7afcfSStefano Zampini     /* Set interior change in the matrix */
63641dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6365bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6366906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6367a717540cSStefano Zampini       }
63681dd7afcfSStefano Zampini     } else {
63691dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
63701dd7afcfSStefano Zampini       PetscScalar    *aa;
63711dd7afcfSStefano Zampini       PetscInt       n;
63721dd7afcfSStefano Zampini       PetscBool      flg_row;
63731dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
63741dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
63751dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
63761dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
63771dd7afcfSStefano Zampini       }
63781dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
63791dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
63801dd7afcfSStefano Zampini     }
6381a717540cSStefano Zampini 
6382a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6383a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6384a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6385a717540cSStefano Zampini     }
6386a717540cSStefano Zampini 
6387a717540cSStefano Zampini 
6388a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6389a717540cSStefano Zampini     /*
6390a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6391a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6392a717540cSStefano Zampini 
6393a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6394a717540cSStefano Zampini 
6395a6b551f4SStefano 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)
6396a6b551f4SStefano Zampini 
6397a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6398a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6399a717540cSStefano Zampini             |              ...                        |
6400a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6401a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6402a717540cSStefano Zampini 
6403a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6404a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6405a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6406a6b551f4SStefano Zampini 
6407a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6408a717540cSStefano Zampini     */
6409a717540cSStefano Zampini     if (qr_needed) {
6410984c4197SStefano Zampini       /* space to store Q */
6411854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
64124e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
64134e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6414984c4197SStefano Zampini       /* first we issue queries for optimal work */
64153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
64173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6418984c4197SStefano Zampini       lqr_work = -1;
64193f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6420984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6421984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6422785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6423984c4197SStefano Zampini       lgqr_work = -1;
64243f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
64253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
64263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
64273f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
64283f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6429c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6430c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6431984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6432785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6433984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6434785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6435a717540cSStefano Zampini       /* allocating workspace for check */
6436a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6437cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6438a717540cSStefano Zampini       }
6439a717540cSStefano Zampini     }
6440984c4197SStefano Zampini     /* array to store whether a node is primal or not */
64414641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6442473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
64430e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
6444eee23b56SStefano Zampini     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
644539e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
644639e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
644739e2fb2aSStefano Zampini     }
644839e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6449984c4197SStefano Zampini 
6450a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
64519162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
64529162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
64534641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6454984c4197SStefano Zampini         /* get constraint info */
64559162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6456984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6457984c4197SStefano Zampini 
6458984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
64599162d606SStefano 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);
6460674ae819SStefano Zampini         }
6461984c4197SStefano Zampini 
6462fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6463a717540cSStefano Zampini 
6464a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6465a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
64669162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6467a717540cSStefano Zampini           }
6468984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
64699162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6470984c4197SStefano Zampini 
6471984c4197SStefano Zampini           /* compute QR decomposition of constraints */
64723f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
64733f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
64743f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6475674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64763f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6477984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6478674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6479984c4197SStefano Zampini 
6480984c4197SStefano Zampini           /* explictly compute R^-T */
6481984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6482984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
64833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
64843f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
64853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
64863f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6487984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64883f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6489984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6490984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6491984c4197SStefano Zampini 
6492a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
64933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
64943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
64953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
64963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6497984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6498c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6499c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6500984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6501984c4197SStefano Zampini 
6502984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6503984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6504984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
65053f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
65063f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
65073f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
65083f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
65093f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
65103f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6511984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
65129162d606SStefano 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));
6513984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
65149162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6515984c4197SStefano Zampini 
6516984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
65179162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6518984c4197SStefano Zampini           /* insert cols for primal dofs */
6519984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6520984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
65219162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6522906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6523984c4197SStefano Zampini           }
6524984c4197SStefano Zampini           /* insert cols for dual dofs */
6525984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
65269162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6527984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
65289162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6529906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6530984c4197SStefano Zampini               j++;
6531674ae819SStefano Zampini             }
6532674ae819SStefano Zampini           }
6533984c4197SStefano Zampini 
6534984c4197SStefano Zampini           /* check change of basis */
6535984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6536984c4197SStefano Zampini             PetscInt   ii,jj;
6537984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6538c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6539c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6540c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6541c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6542c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6543c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6544984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6545cf5a6209SStefano 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));
6546984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6547984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6548984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6549cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6550c068d9bbSLisandro 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;
6551674ae819SStefano Zampini               }
6552674ae819SStefano Zampini             }
6553984c4197SStefano Zampini             if (!valid_qr) {
655422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6555984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6556984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6557cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6558cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6559674ae819SStefano Zampini                   }
6560c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
6561cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6562984c4197SStefano Zampini                   }
6563984c4197SStefano Zampini                 }
6564984c4197SStefano Zampini               }
6565674ae819SStefano Zampini             } else {
656622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6567674ae819SStefano Zampini             }
6568674ae819SStefano Zampini           }
6569a717540cSStefano Zampini         } else { /* simple transformation block */
6570a717540cSStefano Zampini           PetscInt    row,col;
6571a6b551f4SStefano Zampini           PetscScalar val,norm;
6572a6b551f4SStefano Zampini 
6573a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
65749162d606SStefano 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));
6575a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
65769162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
65779162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6578bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
65799162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6580906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
65819162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6582a717540cSStefano Zampini             } else {
6583a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
65849162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6585a717540cSStefano Zampini                 if (row != col) {
65869162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6587a717540cSStefano Zampini                 } else {
65889162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6589a717540cSStefano Zampini                 }
6590906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6591a717540cSStefano Zampini               }
6592a717540cSStefano Zampini             }
6593a717540cSStefano Zampini           }
659498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
659522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6596a717540cSStefano Zampini           }
6597674ae819SStefano Zampini         }
6598984c4197SStefano Zampini       } else {
6599984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
66009162d606SStefano 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);
6601674ae819SStefano Zampini         }
6602674ae819SStefano Zampini       }
6603674ae819SStefano Zampini     }
6604a717540cSStefano Zampini 
6605a717540cSStefano Zampini     /* free workspace */
6606a717540cSStefano Zampini     if (qr_needed) {
6607984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6608cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6609984c4197SStefano Zampini       }
6610984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6611984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6612984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6613984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6614984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6615674ae819SStefano Zampini     }
6616a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6617906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6618906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6619906d46d4SStefano Zampini 
6620906d46d4SStefano Zampini     /* assembling of global change of variable */
662188c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6622bbb9e6c6SStefano Zampini       Mat      tmat;
662316f15bc4SStefano Zampini       PetscInt bs;
662416f15bc4SStefano Zampini 
6625906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6626906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6627bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6628bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6629487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6630487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6631bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6632bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
663316f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
663416f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6635906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6636bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6637487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6638bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6639bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6640bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6641e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6642e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6643bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6644bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
664588c03ad3SStefano Zampini 
6646906d46d4SStefano Zampini       /* check */
6647906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6648906d46d4SStefano Zampini         PetscReal error;
6649906d46d4SStefano Zampini         Vec       x,x_change;
6650906d46d4SStefano Zampini 
6651906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6652906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6653906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6654906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6655e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6656e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6657bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6658e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6659e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6660906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6661906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6662906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6663637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6664637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6665637e8532SStefano Zampini         }
6666906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6667906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6668906d46d4SStefano Zampini       }
6669b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6670b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6671b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6672bf3a8328SStefano Zampini 
667313903a91SSatish 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");
6674b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6675ac632422SStefano Zampini           Mat                    S_new,tmat;
6676bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6677bbb9e6c6SStefano Zampini 
6678bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
66797dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6680bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6681bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6682bf3a8328SStefano Zampini             IS                     is_V;
6683b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6684b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6685b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6686b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6687b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6688bf3a8328SStefano Zampini           }
6689bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6690ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6691b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6692ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6693bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6694bf3a8328SStefano Zampini             const PetscScalar *array;
6695bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6696bf3a8328SStefano Zampini             PetscInt          i,n_V;
6697bf3a8328SStefano Zampini 
6698b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6699b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6700b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6701b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6702b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6703b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6704b087196eSStefano Zampini               PetscScalar val;
6705b087196eSStefano Zampini               PetscInt    idx;
6706b087196eSStefano Zampini 
6707b087196eSStefano Zampini               idx = idxs_V[i];
6708b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6709b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6710b087196eSStefano Zampini             }
6711b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6712b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6713bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6714bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6715bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6716bf3a8328SStefano Zampini           }
6717ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6718ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6719ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6720ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6721b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6722ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6723bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6724b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6725bf3a8328SStefano Zampini             }
6726ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6727ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6728ac632422SStefano Zampini           }
6729b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
673088c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6731b96c3477SStefano Zampini         }
6732c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6733b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6734c9db6a07SStefano Zampini           PetscInt i;
6735c9db6a07SStefano Zampini 
6736c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6737c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6738c9db6a07SStefano Zampini           }
6739c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6740c9db6a07SStefano Zampini         }
6741b96c3477SStefano Zampini       }
674216909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
674316909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
674416909a7fSStefano Zampini       } else {
6745906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
674616909a7fSStefano Zampini       }
67471dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
674827b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
674972b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
675072b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
675172b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
675272b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
675372b8c272SStefano Zampini     }
67541dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
675527b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6756b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6757b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6758906d46d4SStefano Zampini     } else {
67591dd7afcfSStefano Zampini       Mat benign_global = NULL;
676027b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
67611dd7afcfSStefano Zampini         Mat M;
67621dd7afcfSStefano Zampini 
67639e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
67649e9b7b1fSStefano Zampini         ierr = VecCopy(matis->counter,pcis->vec1_N);CHKERRQ(ierr);
67659e9b7b1fSStefano Zampini         ierr = VecReciprocal(pcis->vec1_N);CHKERRQ(ierr);
67669e9b7b1fSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global);CHKERRQ(ierr);
67679e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
67681dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
67691dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
6770906d46d4SStefano Zampini         } else {
67719e9b7b1fSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M);CHKERRQ(ierr);
67729e9b7b1fSStefano Zampini           ierr = MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES);CHKERRQ(ierr);
6773906d46d4SStefano Zampini         }
67749e9b7b1fSStefano Zampini         ierr = MatISSetLocalMat(benign_global,M);CHKERRQ(ierr);
67759e9b7b1fSStefano Zampini         ierr = MatDestroy(&M);CHKERRQ(ierr);
67769e9b7b1fSStefano Zampini         ierr = MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67779e9b7b1fSStefano Zampini         ierr = MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67781dd7afcfSStefano Zampini       }
67791dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
67801dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
67811dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
678227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
67831dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
67841dd7afcfSStefano Zampini       }
67851dd7afcfSStefano Zampini     }
678616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
678716909a7fSStefano Zampini       IS             is_global;
678816909a7fSStefano Zampini       const PetscInt *gidxs;
678916909a7fSStefano Zampini 
679016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
679116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
679216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
67937dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
679416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
679516909a7fSStefano Zampini     }
67961dd7afcfSStefano Zampini   }
67971dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
67981dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6799b9b85e73SStefano Zampini   }
6800a717540cSStefano Zampini 
680172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
68024f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
68034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
68044f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
68054f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6806019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6807019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6808019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6809019a44ceSStefano Zampini     }
6810019a44ceSStefano Zampini 
6811019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6812727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6813727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
68149f47a83aSStefano 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);
6815c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
68160e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
68179f47a83aSStefano 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);
6818727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6819727cdba6SStefano Zampini       }
68200e6343abSStefano Zampini     }
6821727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6822b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
682372b8c272SStefano Zampini   }
682472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6825727cdba6SStefano Zampini 
6826a717540cSStefano Zampini   /* flush dbg viewer */
6827b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6828b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6829b8ffe317SStefano Zampini   }
6830a717540cSStefano Zampini 
6831e310c8b4SStefano Zampini   /* free workspace */
6832a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
68334641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
683408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
68359162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
68369162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
683708122e43SStefano Zampini   } else {
68389162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
68399162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
68409162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
684108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
684208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
68439162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
68449162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
684508122e43SStefano Zampini   }
6846674ae819SStefano Zampini   PetscFunctionReturn(0);
6847674ae819SStefano Zampini }
684804a6f24aSStefano Zampini /* #undef PETSC_MISSING_LAPACK_GESVD */
6849674ae819SStefano Zampini 
6850674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6851674ae819SStefano Zampini {
685271582508SStefano Zampini   ISLocalToGlobalMapping map;
6853674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6854674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
685566da6bd7Sstefano_zampini   PetscInt               i,N;
685666da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
685766da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6858674ae819SStefano Zampini 
6859674ae819SStefano Zampini   PetscFunctionBegin;
68608af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6861b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
68628e61c736SStefano Zampini     /* Reset previously computed graph */
68638e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6864674ae819SStefano Zampini     /* Init local Graph struct */
68657fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
686671582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6867be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6868674ae819SStefano Zampini 
68697a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
68707a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
68717a0e7b2cSstefano_zampini     }
6872575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
6873ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %D, expected %D\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
68749577ea80SStefano Zampini 
6875674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
687666da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
68774d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
68784d379d7bSStefano Zampini       PetscInt  nvtxs;
6879e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6880674ae819SStefano Zampini 
68812fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
68822fffb893SStefano Zampini       if (flg_row) {
68834d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6884b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
68852fffb893SStefano Zampini       }
68862fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
688766da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6888674ae819SStefano Zampini     }
68899b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
68909b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6891674ae819SStefano Zampini     }
6892674ae819SStefano Zampini 
6893ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
6894ab8c8b98SStefano Zampini       PetscReal    *lcoords;
6895ab8c8b98SStefano Zampini       PetscInt     n;
6896ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
6897ab8c8b98SStefano Zampini 
6898ab8c8b98SStefano 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);
6899ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
6900ab8c8b98SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
6901ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
6902ab8c8b98SStefano Zampini       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRQ(ierr);
6903ab8c8b98SStefano Zampini       ierr = MPI_Type_commit(&dimrealtype);CHKERRQ(ierr);
6904ab8c8b98SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6905ab8c8b98SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords);CHKERRQ(ierr);
6906ab8c8b98SStefano Zampini       ierr = MPI_Type_free(&dimrealtype);CHKERRQ(ierr);
6907ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
6908ab8c8b98SStefano Zampini 
6909ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
6910ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
6911ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
6912ab8c8b98SStefano Zampini     }
6913ab8c8b98SStefano 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);
69141c7a958bSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && !pcbddc->corner_selected);
6915ab8c8b98SStefano Zampini 
6916674ae819SStefano Zampini     /* Setup of Graph */
69174b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
691814f95afaSStefano 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);
6919674ae819SStefano Zampini 
69204f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
69214f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
69224f1b2e48SStefano Zampini       PetscInt *local_subs;
69234f1b2e48SStefano Zampini 
69244f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
69254f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
69264f1b2e48SStefano Zampini         const PetscInt *idxs;
69274f1b2e48SStefano Zampini         PetscInt       nl,j;
69284f1b2e48SStefano Zampini 
69294f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
69304f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
693171582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
69324f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
69334f1b2e48SStefano Zampini       }
69344f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
69354f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
69364f1b2e48SStefano Zampini     }
69378af8fcf9SStefano Zampini   }
69384f1b2e48SStefano Zampini 
6939cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6940674ae819SStefano Zampini     /* Graph's connected components analysis */
6941674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
694271582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
69438af8fcf9SStefano Zampini   }
694466da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6945674ae819SStefano Zampini   PetscFunctionReturn(0);
6946674ae819SStefano Zampini }
6947674ae819SStefano Zampini 
69489a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
69499a7d3425SStefano Zampini {
69509a7d3425SStefano Zampini   PetscInt       i,j;
69519a7d3425SStefano Zampini   PetscScalar    *alphas;
69529a7d3425SStefano Zampini   PetscErrorCode ierr;
69539a7d3425SStefano Zampini 
69549a7d3425SStefano Zampini   PetscFunctionBegin;
69558c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
6956785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
69578c0031efSStefano Zampini   ierr = VecNormalize(vecs[0],NULL);CHKERRQ(ierr);
69588c0031efSStefano Zampini   for (i=1;i<n;i++) {
69598c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
69608c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
69618c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
69629a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
69639a7d3425SStefano Zampini   }
69649a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
69659a7d3425SStefano Zampini   PetscFunctionReturn(0);
69669a7d3425SStefano Zampini }
69679a7d3425SStefano Zampini 
6968bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6969e7931f94SStefano Zampini {
697057de7509SStefano Zampini   Mat            A;
6971e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6972e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
697352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
697452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6975bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
697657de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
697727b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
697827b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
697927b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
698027b6a85dSStefano Zampini   MPI_Comm       subcomm;
698152e5ac9dSStefano Zampini   PetscErrorCode ierr;
6982a57a6d2fSStefano Zampini 
6983e7931f94SStefano Zampini   PetscFunctionBegin;
698457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
698557de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6986fbfcfee5SBarry 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);
698757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
698857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
698957de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
699057de7509SStefano Zampini 
699157de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
699257de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
699357de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
699457de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
699557de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6996bb360cb4SStefano Zampini   im_active = !!n;
699757de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
699857de7509SStefano Zampini   void_procs = size - active_procs;
699957de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
700057de7509SStefano Zampini   if (void_procs) {
700157de7509SStefano Zampini     PetscInt ncand;
700257de7509SStefano Zampini 
700357de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
700457de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
700557de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
700657de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
700757de7509SStefano Zampini       if (!procs_candidates[i]) {
700857de7509SStefano Zampini         procs_candidates[ncand++] = i;
700957de7509SStefano Zampini       }
701057de7509SStefano Zampini     }
701157de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
701257de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
701357de7509SStefano Zampini   }
701457de7509SStefano Zampini 
7015bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
701614f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
7017bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7018bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
701914f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
702014f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
702114f0bfb9SStefano Zampini     else dest = rank;
702257de7509SStefano Zampini     if (im_active) {
702357de7509SStefano Zampini       issize = 1;
702457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
702514f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
702657de7509SStefano Zampini       } else {
702714f0bfb9SStefano Zampini         isidx = dest;
702857de7509SStefano Zampini       }
702957de7509SStefano Zampini     } else {
703057de7509SStefano Zampini       issize = 0;
703157de7509SStefano Zampini       isidx = -1;
703257de7509SStefano Zampini     }
7033bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
703457de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7035daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
703657de7509SStefano Zampini     PetscFunctionReturn(0);
703757de7509SStefano Zampini   }
7038c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7039c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
704027b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7041e7931f94SStefano Zampini 
7042e7931f94SStefano Zampini   /* Get info on mapping */
70433bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7044e7931f94SStefano Zampini 
7045e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7046785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7047e7931f94SStefano Zampini   xadj[0] = 0;
7048e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7049785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7050785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7051bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
705227b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
705327b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
705427b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7055e7931f94SStefano Zampini 
705627b6a85dSStefano Zampini   xadj_count = 0;
70572b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
705827b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
705927b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7060d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7061d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7062d023bfaeSStefano Zampini         xadj_count++;
706327b6a85dSStefano Zampini         break;
706427b6a85dSStefano Zampini       }
7065e7931f94SStefano Zampini     }
7066e7931f94SStefano Zampini   }
7067d023bfaeSStefano Zampini   xadj[1] = xadj_count;
706827b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
70693bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7070e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7071e7931f94SStefano Zampini 
70723837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7073e7931f94SStefano Zampini 
707427b6a85dSStefano Zampini   /* Restrict work on active processes only */
707527b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
707627b6a85dSStefano Zampini   if (void_procs) {
707727b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
707827b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
707927b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
708027b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
708127b6a85dSStefano Zampini   } else {
708227b6a85dSStefano Zampini     psubcomm = NULL;
708327b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
708427b6a85dSStefano Zampini   }
708527b6a85dSStefano Zampini 
708627b6a85dSStefano Zampini   v_wgt = NULL;
708727b6a85dSStefano Zampini   if (!color) {
7088e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7089e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7090e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7091c8587f34SStefano Zampini   } else {
709252e5ac9dSStefano Zampini     Mat             subdomain_adj;
709352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
709452e5ac9dSStefano Zampini     MatPartitioning partitioner;
709527b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
709652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
709757de7509SStefano Zampini     PetscMPIInt     size;
7098b0c7d250SStefano Zampini     PetscBool       aggregate;
7099b0c7d250SStefano Zampini 
710027b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
710127b6a85dSStefano Zampini     if (void_procs) {
710227b6a85dSStefano Zampini       PetscInt prank = rank;
7103785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
710427b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
7105e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7106e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7107c8587f34SStefano Zampini       }
7108e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
710927b6a85dSStefano Zampini     } else {
711027b6a85dSStefano Zampini       oldranks = NULL;
711127b6a85dSStefano Zampini     }
7112b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
711327b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7114b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7115b0c7d250SStefano Zampini       PetscMPIInt nrank;
7116b0c7d250SStefano Zampini       PetscScalar *vals;
7117b0c7d250SStefano Zampini 
711827b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
7119b0c7d250SStefano Zampini       lrows = 0;
7120b0c7d250SStefano Zampini       if (nrank<redprocs) {
7121b0c7d250SStefano Zampini         lrows = size/redprocs;
7122b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7123b0c7d250SStefano Zampini       }
712427b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7125b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7126b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7127b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7128b0c7d250SStefano Zampini       row = nrank;
7129b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7130b0c7d250SStefano Zampini       cols = adjncy;
7131b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7132b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7133b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7134b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7135b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
713652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
713752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
713852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7139b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
714027b6a85dSStefano Zampini       if (use_vwgt) {
714127b6a85dSStefano Zampini         Vec               v;
714227b6a85dSStefano Zampini         const PetscScalar *array;
714327b6a85dSStefano Zampini         PetscInt          nl;
714427b6a85dSStefano Zampini 
714527b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7146bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
714727b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
714827b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
714927b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
715027b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
715127b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
715222db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
715327b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
715427b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
715527b6a85dSStefano Zampini       }
7156b0c7d250SStefano Zampini     } else {
715727b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
715827b6a85dSStefano Zampini       if (use_vwgt) {
715927b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7160bb360cb4SStefano Zampini         v_wgt[0] = n;
716127b6a85dSStefano Zampini       }
7162b0c7d250SStefano Zampini     }
716322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7164e7931f94SStefano Zampini 
7165e7931f94SStefano Zampini     /* Partition */
716627b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7167e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
716827b6a85dSStefano Zampini     if (v_wgt) {
7169e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7170c8587f34SStefano Zampini     }
717157de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
717257de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7173e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7174e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
717522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7176e7931f94SStefano Zampini 
717752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
71786583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
717952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
718052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
718157de7509SStefano Zampini     if (!aggregate) {
718257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
718327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
718427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
718527b6a85dSStefano Zampini #endif
718657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
718727b6a85dSStefano Zampini       } else if (oldranks) {
7188b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
718927b6a85dSStefano Zampini       } else {
719027b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
719157de7509SStefano Zampini       }
719228143c3dSStefano Zampini     } else {
71937fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7194b0c7d250SStefano Zampini       PetscMPIInt tag;
7195b0c7d250SStefano Zampini       MPI_Request *reqs;
7196b0c7d250SStefano Zampini 
7197b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7198b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7199b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
720027b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
720128143c3dSStefano Zampini       }
72027fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
7203b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7204b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
720557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
720627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
720727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
720827b6a85dSStefano Zampini #endif
72097fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
721027b6a85dSStefano Zampini       } else if (oldranks) {
72117fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
721227b6a85dSStefano Zampini       } else {
72137fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7214e7931f94SStefano Zampini       }
721557de7509SStefano Zampini     }
721652e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7217e7931f94SStefano Zampini     /* clean up */
7218e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
721952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7220e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7221e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7222e7931f94SStefano Zampini   }
722327b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
722457de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7225e7931f94SStefano Zampini 
7226e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7227e7931f94SStefano Zampini   i = 1;
722827b6a85dSStefano Zampini   if (!color) i=0;
722957de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7230e7931f94SStefano Zampini   PetscFunctionReturn(0);
7231e7931f94SStefano Zampini }
7232e7931f94SStefano Zampini 
7233e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7234e7931f94SStefano Zampini 
72351e0482f5SStefano 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[])
7236e7931f94SStefano Zampini {
723770cf5478SStefano Zampini   Mat                    local_mat;
7238e7931f94SStefano Zampini   IS                     is_sends_internal;
72399d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
72401ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
72419d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7242e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7243e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7244e7931f94SStefano Zampini   const PetscInt*        is_indices;
7245e7931f94SStefano Zampini   MatType                new_local_type;
7246e7931f94SStefano Zampini   /* buffers */
7247e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
724828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
72499d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
7250e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
72511ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7252e7931f94SStefano Zampini   /* MPI */
725328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
725428143c3dSStefano Zampini   PetscSubcomm           subcomm;
7255e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
725628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
725728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
72581ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
72591ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
72601ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7261e7931f94SStefano Zampini   PetscErrorCode         ierr;
7262e7931f94SStefano Zampini 
7263e7931f94SStefano Zampini   PetscFunctionBegin;
726457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7265e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7266fbfcfee5SBarry 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);
726757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
726857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
726957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
727057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
727157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
72721ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
72731ae86dd6SStefano Zampini   if (nvecs) {
72741ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
72751ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
72761ae86dd6SStefano Zampini   }
727757de7509SStefano Zampini   /* further checks */
7278e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7279e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7280e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7281e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7282e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
728357de7509SStefano Zampini   if (reuse && *mat_n) {
728470cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
728557de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
728670cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
728728143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
728870cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
728970cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
729070cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
729170cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
729270cf5478SStefano Zampini   }
7293e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7294e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
729557de7509SStefano Zampini 
7296e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7297e7931f94SStefano Zampini   if (!is_sends) {
729828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7299bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7300c8587f34SStefano Zampini   } else {
7301e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7302e7931f94SStefano Zampini     is_sends_internal = is_sends;
7303c8587f34SStefano Zampini   }
7304e7931f94SStefano Zampini 
7305e7931f94SStefano Zampini   /* get comm */
7306a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7307e7931f94SStefano Zampini 
7308e7931f94SStefano Zampini   /* compute number of sends */
7309e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7310e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7311e7931f94SStefano Zampini 
7312e7931f94SStefano Zampini   /* compute number of receives */
7313e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
7314785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
7315e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
7316e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7317e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7318e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7319e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7320e7931f94SStefano Zampini 
732128143c3dSStefano Zampini   /* restrict comm if requested */
732228143c3dSStefano Zampini   subcomm = 0;
732328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
732428143c3dSStefano Zampini   if (restrict_comm) {
7325779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7326779c1cceSStefano Zampini 
732728143c3dSStefano Zampini     color = 0;
732853a05cb3SStefano Zampini     if (restrict_full) {
732953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
733053a05cb3SStefano Zampini     } else {
733153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
733253a05cb3SStefano Zampini     }
7333b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
733428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
733528143c3dSStefano Zampini     /* check if reuse has been requested */
733657de7509SStefano Zampini     if (reuse) {
733728143c3dSStefano Zampini       if (*mat_n) {
733828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
733928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
734028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
734128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
734228143c3dSStefano Zampini       } else {
734328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
734428143c3dSStefano Zampini       }
734528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7346779c1cceSStefano Zampini       PetscMPIInt rank;
7347779c1cceSStefano Zampini 
7348779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
734928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
735028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
735128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7352306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
735328143c3dSStefano Zampini     }
735428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
735528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
735628143c3dSStefano Zampini   } else {
735728143c3dSStefano Zampini     comm_n = comm;
735828143c3dSStefano Zampini   }
735928143c3dSStefano Zampini 
7360e7931f94SStefano Zampini   /* prepare send/receive buffers */
7361785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
7362e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7363785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
7364e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
736528143c3dSStefano Zampini   if (nis) {
7366854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
736728143c3dSStefano Zampini   }
7368e7931f94SStefano Zampini 
736928143c3dSStefano Zampini   /* Get data from local matrices */
73706c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7371e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7372e7931f94SStefano Zampini     /*
7373e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7374e7931f94SStefano Zampini        send_buffer_idxs should contain:
7375e7931f94SStefano Zampini        - MatType_PRIVATE type
7376e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7377e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7378e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7379e7931f94SStefano Zampini     */
73806c4ed002SBarry Smith   else {
7381e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
73823bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7383854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7384e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7385e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
73863bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7387e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
73883bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7389e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7390e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7391e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7392e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7393c8587f34SStefano Zampini     }
7394c8587f34SStefano Zampini   }
7395e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
739628143c3dSStefano Zampini   /* additional is (if any) */
739728143c3dSStefano Zampini   if (nis) {
739828143c3dSStefano Zampini     PetscMPIInt psum;
739928143c3dSStefano Zampini     PetscInt j;
740028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
740128143c3dSStefano Zampini       PetscInt plen;
740228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
740328143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
740428143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
740528143c3dSStefano Zampini     }
7406854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
740728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
740828143c3dSStefano Zampini       PetscInt plen;
740928143c3dSStefano Zampini       const PetscInt *is_array_idxs;
741028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
741128143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
741228143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
741328143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
741428143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
741528143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
741628143c3dSStefano Zampini     }
741728143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
741828143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
741928143c3dSStefano Zampini     }
742028143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
742128143c3dSStefano Zampini   }
74223b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
742328143c3dSStefano Zampini 
7424e7931f94SStefano Zampini   buf_size_idxs = 0;
7425e7931f94SStefano Zampini   buf_size_vals = 0;
742628143c3dSStefano Zampini   buf_size_idxs_is = 0;
74271ae86dd6SStefano Zampini   buf_size_vecs = 0;
7428e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7429e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7430e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
743128143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
74321ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7433e7931f94SStefano Zampini   }
7434785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7435785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
743695ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
74371ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7438e7931f94SStefano Zampini 
7439e7931f94SStefano Zampini   /* get new tags for clean communications */
7440e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7441e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
744228143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
74431ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7444e7931f94SStefano Zampini 
7445e7931f94SStefano Zampini   /* allocate for requests */
7446785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7447785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
744895ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
74491ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7450785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7451785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
745295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
74531ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7454e7931f94SStefano Zampini 
7455e7931f94SStefano Zampini   /* communications */
7456e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7457e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
745828143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
74591ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7460e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7461e7931f94SStefano Zampini     source_dest = onodes[i];
7462e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7463e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7464e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7465e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
746628143c3dSStefano Zampini     if (nis) {
746757de7509SStefano Zampini       source_dest = onodes_is[i];
746828143c3dSStefano 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);
746928143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
747028143c3dSStefano Zampini     }
74711ae86dd6SStefano Zampini     if (nvecs) {
74721ae86dd6SStefano Zampini       source_dest = onodes[i];
74731ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
74741ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
74751ae86dd6SStefano Zampini     }
7476e7931f94SStefano Zampini   }
7477e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7478e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7479e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7480e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
748128143c3dSStefano Zampini     if (nis) {
748228143c3dSStefano 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);
748328143c3dSStefano Zampini     }
74841ae86dd6SStefano Zampini     if (nvecs) {
74851ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74861ae86dd6SStefano 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);
74871ae86dd6SStefano Zampini     }
7488e7931f94SStefano Zampini   }
7489e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7490e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7491e7931f94SStefano Zampini 
7492e7931f94SStefano Zampini   /* assemble new l2g map */
7493e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7494e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
74959d30be91SStefano Zampini   new_local_rows = 0;
7496e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
74979d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7498e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7499e7931f94SStefano Zampini   }
75009d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7501e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
75029d30be91SStefano Zampini   new_local_rows = 0;
7503e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
75049d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
75059d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7506e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7507e7931f94SStefano Zampini   }
75089d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
75099d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7510e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7511e7931f94SStefano Zampini 
7512e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7513e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7514e7931f94SStefano 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) */
7515e7931f94SStefano Zampini   if (n_recvs) {
751628143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7517e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7518e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7519e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7520e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7521e7931f94SStefano Zampini         break;
7522e7931f94SStefano Zampini       }
7523e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7524e7931f94SStefano Zampini     }
7525e7931f94SStefano Zampini     switch (new_local_type_private) {
752628143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7527e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7528e7931f94SStefano Zampini         bs = 1;
7529e7931f94SStefano Zampini         break;
7530e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7531e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7532e7931f94SStefano Zampini         bs = 1;
7533e7931f94SStefano Zampini         break;
7534e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7535e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7536e7931f94SStefano Zampini         break;
7537e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7538e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7539e7931f94SStefano Zampini         break;
7540e7931f94SStefano Zampini       default:
7541fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7542e7931f94SStefano Zampini         break;
7543e7931f94SStefano Zampini     }
7544ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7545ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
754628143c3dSStefano Zampini     bs = 1;
7547e7931f94SStefano Zampini   }
7548e7931f94SStefano Zampini 
754970cf5478SStefano Zampini   /* create MATIS object if needed */
755057de7509SStefano Zampini   if (!reuse) {
7551e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7552e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
755370cf5478SStefano Zampini   } else {
755470cf5478SStefano Zampini     /* it also destroys the local matrices */
755557de7509SStefano Zampini     if (*mat_n) {
755670cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
755757de7509SStefano Zampini     } else { /* this is a fake object */
755857de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
755957de7509SStefano Zampini     }
756070cf5478SStefano Zampini   }
756170cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7562e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
75639d30be91SStefano Zampini 
75649d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
75659d30be91SStefano Zampini 
75669d30be91SStefano Zampini   /* Global to local map of received indices */
75679d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
75689d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
75699d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
75709d30be91SStefano Zampini 
75719d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
75729d30be91SStefano Zampini   buf_size_idxs = 0;
75739d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
75749d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
75759d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
75769d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
75779d30be91SStefano Zampini   }
75789d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
75799d30be91SStefano Zampini 
75809d30be91SStefano Zampini   /* set preallocation */
75819d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
75829d30be91SStefano Zampini   if (!newisdense) {
75839d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
75849d30be91SStefano Zampini 
75859d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
75869d30be91SStefano Zampini     if (n_recvs) {
75879d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
75889d30be91SStefano Zampini     }
75899d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
75909d30be91SStefano Zampini       PetscInt j;
75919d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
75929d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
75939d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
75949d30be91SStefano Zampini         }
75959d30be91SStefano Zampini       } else {
75969d30be91SStefano Zampini         /* TODO */
75979d30be91SStefano Zampini       }
75989d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
75999d30be91SStefano Zampini     }
76009d30be91SStefano Zampini     if (new_local_nnz) {
76019d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
76029d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
76039d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
76049d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76059d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
76069d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
76079d30be91SStefano Zampini     } else {
76089d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76099d30be91SStefano Zampini     }
76109d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
76119d30be91SStefano Zampini   } else {
76129d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
76139d30be91SStefano Zampini   }
7614e7931f94SStefano Zampini 
7615e7931f94SStefano Zampini   /* set values */
7616e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
76179d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7618e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7619e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7620e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
76219d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7622e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7623e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7624e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
762528143c3dSStefano Zampini     } else {
762628143c3dSStefano Zampini       /* TODO */
7627e7931f94SStefano Zampini     }
7628e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7629e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7630e7931f94SStefano Zampini   }
7631e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7632e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76333b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
763470cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
763570cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76369d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7637e7931f94SStefano Zampini 
7638dfd14d43SStefano Zampini #if 0
763928143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7640e7931f94SStefano Zampini     Vec       lvec,rvec;
7641e7931f94SStefano Zampini     PetscReal infty_error;
7642e7931f94SStefano Zampini 
76432a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7644e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7645e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7646e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
764770cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7648e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7649e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7650e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7651e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7652e7931f94SStefano Zampini   }
765328143c3dSStefano Zampini #endif
7654e7931f94SStefano Zampini 
765528143c3dSStefano Zampini   /* assemble new additional is (if any) */
765628143c3dSStefano Zampini   if (nis) {
765728143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
765828143c3dSStefano Zampini 
765928143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7660854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
766128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
766228143c3dSStefano Zampini     psum = 0;
766328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
766428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
766528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
766628143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
766728143c3dSStefano Zampini         psum += plen;
766828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
766928143c3dSStefano Zampini       }
767028143c3dSStefano Zampini     }
7671854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7672854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
767328143c3dSStefano Zampini     for (i=1;i<nis;i++) {
767428143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
767528143c3dSStefano Zampini     }
767628143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
767728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
767828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
767928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
768028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
768128143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
768228143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
768328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
768428143c3dSStefano Zampini       }
768528143c3dSStefano Zampini     }
768628143c3dSStefano Zampini     for (i=0;i<nis;i++) {
768728143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
768828143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
768928143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
769028143c3dSStefano Zampini     }
769128143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
769228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
769328143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
769428143c3dSStefano Zampini   }
7695e7931f94SStefano Zampini   /* free workspace */
769628143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7697e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7698e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7699e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7700e7931f94SStefano Zampini   if (isdense) {
7701e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7702e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
77033b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7704e7931f94SStefano Zampini   } else {
7705e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7706e7931f94SStefano Zampini   }
770728143c3dSStefano Zampini   if (nis) {
770828143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
770928143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
771028143c3dSStefano Zampini   }
77111ae86dd6SStefano Zampini 
77121ae86dd6SStefano Zampini   if (nvecs) {
77131ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77141ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
77151ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77161ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
77171ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
77181ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
77191ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
77201ae86dd6SStefano Zampini     /* set values */
77211ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
77221ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
77231ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77241ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
77251ae86dd6SStefano Zampini       PetscInt j;
77261ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
77271ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
77281ae86dd6SStefano Zampini       }
77291ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
77301ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
77311ae86dd6SStefano Zampini     }
77321ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
77331ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
77341ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
77351ae86dd6SStefano Zampini   }
77361ae86dd6SStefano Zampini 
77371ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
77381ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7739e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7740e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
77411ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
774228143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7743e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7744e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
77451ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
774628143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7747e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7748e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7749e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7750e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7751e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
775228143c3dSStefano Zampini   if (nis) {
775328143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
775428143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
775528143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
775628143c3dSStefano Zampini   }
775728143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
775828143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
775928143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
776028143c3dSStefano Zampini     for (i=0;i<nis;i++) {
776128143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
776228143c3dSStefano Zampini     }
77631ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
77641ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
77651ae86dd6SStefano Zampini     }
776653a05cb3SStefano Zampini     *mat_n = NULL;
776728143c3dSStefano Zampini   }
7768e7931f94SStefano Zampini   PetscFunctionReturn(0);
7769e7931f94SStefano Zampini }
7770a57a6d2fSStefano Zampini 
777112edc857SStefano Zampini /* temporary hack into ksp private data structure */
7772af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
777312edc857SStefano Zampini 
7774c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7775c8587f34SStefano Zampini {
7776c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7777c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
777820a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
77791ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
77801e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
77819881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
778220a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
77836e683305SStefano Zampini   IS                     coarse_is,*isarray;
77846e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
778530368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7786f9eb5b7dSStefano Zampini   PC                     pc_temp;
7787c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7788c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7789f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
77907274672aSStefano Zampini   PetscBool              coarse_reuse;
77911e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
779268457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
779322bc73bbSStefano Zampini   PetscScalar            *array;
779457de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
779557de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
77967de4f681Sstefano_zampini   PetscMPIInt            commsize;
77979881197aSStefano Zampini   PetscErrorCode         ierr;
7798fdc09c96SStefano Zampini 
7799c8587f34SStefano Zampini   PetscFunctionBegin;
780043371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
7801c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
780268457ee5SStefano 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 */
7803fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
78045a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
78057de4f681Sstefano_zampini 
78067de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7807fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7808f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7809f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7810f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7811fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
781251bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
781351bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7814727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7815fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7816fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7817fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7818f4ddd8eeSStefano Zampini       }
7819fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7820fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7821f4ddd8eeSStefano Zampini     }
782270cf5478SStefano Zampini     /* reset any subassembling information */
782357de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
782470cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
782557de7509SStefano Zampini     }
78266e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7827fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7828f4ddd8eeSStefano Zampini   }
782957de7509SStefano Zampini   /* assemble coarse matrix */
783057de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
783157de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
783257de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
783357de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
783418a45a71SStefano Zampini   } else {
783557de7509SStefano Zampini     coarse_mat = NULL;
783657de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
78376e683305SStefano Zampini   }
7838e7931f94SStefano Zampini 
7839abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7840abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7841abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7842abbbba34SStefano Zampini 
7843abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
784422bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
784522bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
784622bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
784722bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7848e176bc59SStefano 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);
78496e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
78506e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78516e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7852abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7853abbbba34SStefano Zampini 
785457de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
785557de7509SStefano Zampini   im_active = !!(pcis->n);
785657de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
785757de7509SStefano Zampini 
785814f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
785957de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
786057de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
78617de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
786257de7509SStefano Zampini   coarse_mat_is = NULL;
786357de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
786457de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
78651ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
786657de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
786757de7509SStefano Zampini   if (multilevel_requested) {
786857de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
786957de7509SStefano Zampini     restr = PETSC_FALSE;
787057de7509SStefano Zampini     full_restr = PETSC_FALSE;
787157de7509SStefano Zampini   } else {
787257de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
787357de7509SStefano Zampini     restr = PETSC_TRUE;
787457de7509SStefano Zampini     full_restr = PETSC_TRUE;
787557de7509SStefano Zampini   }
78767de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
787757de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
787857de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7879a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7880bb360cb4SStefano Zampini       if (multilevel_requested) {
7881bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7882bb360cb4SStefano Zampini       } else {
7883bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7884bb360cb4SStefano Zampini       }
7885a198735bSStefano Zampini     } else {
78867de4f681Sstefano_zampini       PetscMPIInt rank;
7887a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
78887de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7889a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7890a198735bSStefano Zampini     }
789157de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
789257de7509SStefano Zampini     PetscInt    psum;
789357de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
789457de7509SStefano Zampini     else psum = 0;
789557de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
78967de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
789757de7509SStefano Zampini   }
789857de7509SStefano Zampini   /* determine if we can go multilevel */
789957de7509SStefano Zampini   if (multilevel_requested) {
790057de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
790157de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
790257de7509SStefano Zampini   }
790357de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
790457de7509SStefano Zampini 
7905e4d548c7SStefano Zampini   /* dump subassembling pattern */
7906e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7907e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7908e4d548c7SStefano Zampini   }
7909e4d548c7SStefano Zampini 
79106e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
79111e0482f5SStefano Zampini   nedcfield = -1;
79121e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
79136e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
79146e683305SStefano Zampini     const PetscInt         *idxs;
79156e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
79166e683305SStefano Zampini 
79176e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
79180be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
79196e683305SStefano Zampini     /* allocate space for temporary storage */
7920854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7921854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
79226e683305SStefano Zampini     /* allocate for IS array */
79236e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
79241e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
79251e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
79261e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
79271e0482f5SStefano Zampini       } else {
79281e0482f5SStefano Zampini         nedcfield = 0;
79291e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
79301e0482f5SStefano Zampini         nisdofs = 1;
79311e0482f5SStefano Zampini       }
79321e0482f5SStefano Zampini     }
79336e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
793427b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
793530368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7936854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
79376e683305SStefano Zampini     /* dofs splitting */
79386e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
79396e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
79401e0482f5SStefano Zampini       if (nedcfield != i) {
79416e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
79426e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
79436e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
79446e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
79451e0482f5SStefano Zampini       } else {
79461e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
79471e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
79481e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7949eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
79501e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
79511e0482f5SStefano Zampini       }
79526e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
795330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
79546e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
79556e683305SStefano Zampini     }
79566e683305SStefano Zampini     /* neumann boundaries */
79576e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
79586e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
79596e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
79606e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
79616e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
79626e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
79636e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
796430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
79656e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
79666e683305SStefano Zampini     }
79676e683305SStefano Zampini     /* free memory */
79686e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
79696e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
79706e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
79716e683305SStefano Zampini   } else {
79726e683305SStefano Zampini     nis = 0;
79736e683305SStefano Zampini     nisdofs = 0;
79746e683305SStefano Zampini     nisneu = 0;
797530368db7SStefano Zampini     nisvert = 0;
79766e683305SStefano Zampini     isarray = NULL;
79776e683305SStefano Zampini   }
79786e683305SStefano Zampini   /* destroy no longer needed map */
79796e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
79806e683305SStefano Zampini 
798157de7509SStefano Zampini   /* subassemble */
798257de7509SStefano Zampini   if (multilevel_allowed) {
79831ae86dd6SStefano Zampini     Vec       vp[1];
79841ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
798557de7509SStefano Zampini     PetscBool reuse,reuser;
79861ae86dd6SStefano Zampini 
798757de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
798857de7509SStefano Zampini     else reuse = PETSC_FALSE;
798957de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
79901ae86dd6SStefano Zampini     vp[0] = NULL;
79911ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
79921ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
79931ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
79941ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
79951ae86dd6SStefano Zampini       nvecs = 1;
79961ae86dd6SStefano Zampini 
79971ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7998a198735bSStefano Zampini         Mat      B,loc_divudotp;
79991ae86dd6SStefano Zampini         Vec      v,p;
80001ae86dd6SStefano Zampini         IS       dummy;
80011ae86dd6SStefano Zampini         PetscInt np;
80021ae86dd6SStefano Zampini 
8003a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8004a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
80051ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
80067dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
80071ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
80081ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
80091ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
80101ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
80111ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
80121ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
80131ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
80141ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
80151ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
80161ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
80171ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
80181ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
801974e2c79eSStefano Zampini       }
80201ae86dd6SStefano Zampini     }
80211ae86dd6SStefano Zampini     if (reuser) {
80221e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
802374e2c79eSStefano Zampini     } else {
80241e0482f5SStefano 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);
80251ae86dd6SStefano Zampini     }
80261ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
80271ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
80281ae86dd6SStefano Zampini       PetscInt    nl;
80291ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
80301ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
80311ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
80321ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
80331ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
80341ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
80351ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
80361ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8037a198735bSStefano Zampini     } else {
8038a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
80391ae86dd6SStefano Zampini     }
80401ae86dd6SStefano Zampini   } else {
80411e0482f5SStefano 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);
80426e683305SStefano Zampini   }
804357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
804457de7509SStefano Zampini     PetscMPIInt size;
8045f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
804657de7509SStefano Zampini     if (!multilevel_allowed) {
8047487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
80486e683305SStefano Zampini     } else {
804957de7509SStefano Zampini       Mat A;
8050779c1cceSStefano Zampini 
805157de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
805257de7509SStefano Zampini       if (coarse_mat_is) {
805357de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
805457de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
805557de7509SStefano Zampini         coarse_mat = coarse_mat_is;
805657de7509SStefano Zampini       }
805757de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
805857de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
805957de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
8060779c1cceSStefano Zampini     }
8061779c1cceSStefano Zampini   }
806257de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
806357de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
80646e683305SStefano Zampini 
80656e683305SStefano Zampini   /* create local to global scatters for coarse problem */
806668457ee5SStefano Zampini   if (compute_vecs) {
80676e683305SStefano Zampini     PetscInt lrows;
80686e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
806957de7509SStefano Zampini     if (coarse_mat) {
807057de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
80716e683305SStefano Zampini     } else {
80726e683305SStefano Zampini       lrows = 0;
80736e683305SStefano Zampini     }
80746e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
80756e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
80766e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
80776e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
80786e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
80796e683305SStefano Zampini   }
80806e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8081c8587f34SStefano Zampini 
8082f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8083f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8084f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8085f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
8086f9eb5b7dSStefano Zampini   } else {
8087f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8088f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
8089c8587f34SStefano Zampini   }
8090c8587f34SStefano Zampini 
80916e683305SStefano Zampini   /* print some info if requested */
80926e683305SStefano Zampini   if (pcbddc->dbg_flag) {
80936e683305SStefano Zampini     if (!multilevel_allowed) {
80946e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
80956e683305SStefano Zampini       if (multilevel_requested) {
80966e683305SStefano 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);
80976e683305SStefano Zampini       } else if (pcbddc->max_levels) {
80986e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
80996e683305SStefano Zampini       }
81006e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
81016e683305SStefano Zampini     }
81026e683305SStefano Zampini   }
81036e683305SStefano Zampini 
81041e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
81051e0482f5SStefano Zampini   coarseG = NULL;
81061e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
81071e0482f5SStefano Zampini     MPI_Comm ccomm;
81081e0482f5SStefano Zampini     if (coarse_mat) {
81091e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
81101e0482f5SStefano Zampini     } else {
81111e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
81121e0482f5SStefano Zampini     }
81131e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
81141e0482f5SStefano Zampini   }
81151e0482f5SStefano Zampini 
8116f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
811757de7509SStefano Zampini   if (coarse_mat) {
81187274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
81196a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
81207274672aSStefano Zampini 
81216e683305SStefano Zampini     if (pcbddc->dbg_flag) {
812257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
81236e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
81246e683305SStefano Zampini     }
8125f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8126312be037SStefano Zampini       char   prefix[256],str_level[16];
8127e604994aSStefano Zampini       size_t len;
81281e0482f5SStefano Zampini 
812957de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8130422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8131c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8132f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
813357de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8134c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
81356e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8136c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
81371e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8138c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8139e604994aSStefano Zampini       /* prefix */
8140e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8141e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8142e604994aSStefano Zampini       if (!pcbddc->current_level) {
8143a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8144a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8145c8587f34SStefano Zampini       } else {
8146e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8147312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8148312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8149a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
815034d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
815135529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8152a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8153e604994aSStefano Zampini       }
8154e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
81553e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
81563e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
81573e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
81583e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8159f9eb5b7dSStefano Zampini       /* allow user customization */
8160f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
81613e3c6dadSStefano Zampini     }
81623e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
816351bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
81643e3c6dadSStefano Zampini     if (nisdofs) {
81653e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
81663e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
81673e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
81683e3c6dadSStefano Zampini       }
81693e3c6dadSStefano Zampini     }
81703e3c6dadSStefano Zampini     if (nisneu) {
81713e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
81723e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8173312be037SStefano Zampini     }
817430368db7SStefano Zampini     if (nisvert) {
817530368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
817630368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
817730368db7SStefano Zampini     }
81781e0482f5SStefano Zampini     if (coarseG) {
81791e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
81801e0482f5SStefano Zampini     }
8181f9eb5b7dSStefano Zampini 
8182f9eb5b7dSStefano Zampini     /* get some info after set from options */
8183f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
8184b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8185b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8186f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8187f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
8188f9eb5b7dSStefano Zampini     }
8189b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
81907274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
81917274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
8192b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8193b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
8194b76f3995Sstefano_zampini     }
81957274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
81964f3a063dSStefano Zampini     if (isredundant) {
81974f3a063dSStefano Zampini       KSP inner_ksp;
81984f3a063dSStefano Zampini       PC  inner_pc;
81999326c5c6Sstefano_zampini 
82004f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
82014f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
82024f3a063dSStefano Zampini     }
8203f9eb5b7dSStefano Zampini 
820457de7509SStefano Zampini     /* parameters which miss an API */
82057274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
820657de7509SStefano Zampini     if (isbddc) {
8207720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
82087274672aSStefano Zampini 
8209720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
821057de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
821127b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
821227b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8213a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8214a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8215a198735bSStefano Zampini         IS                     row,col;
8216a198735bSStefano Zampini         const PetscInt         *gidxs;
8217a198735bSStefano Zampini         PetscInt               n,st,M,N;
8218a198735bSStefano Zampini 
8219a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8220a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
8221a198735bSStefano Zampini         st   = st-n;
8222a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8223a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8224a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8225a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8226a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8227a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8228a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8229a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8230a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8231a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8232a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8233a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8234a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8235a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8236a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8237a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8238a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8239a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8240a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8241a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
82428ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8243a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8244720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8245bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8246720d30f9SStefano Zampini       }
8247d4d8cf7bSStefano Zampini     }
82489881197aSStefano Zampini 
82493301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
82505a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
82513301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
82523301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
82533301b35fSStefano Zampini     }
82543301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
82553301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
82563301b35fSStefano Zampini     }
82573301b35fSStefano Zampini     if (pc->pmat->spd_set) {
82583301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
82593301b35fSStefano Zampini     }
826027b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
826127b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
826227b6a85dSStefano Zampini     }
82636e683305SStefano Zampini     /* set operators */
826404fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
82655f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
82666e683305SStefano Zampini     if (pcbddc->dbg_flag) {
82676e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
82686e683305SStefano Zampini     }
82696e683305SStefano Zampini   }
82701e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
82716e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8272b1ecc7b1SStefano Zampini #if 0
8273b9b85e73SStefano Zampini   {
8274b9b85e73SStefano Zampini     PetscViewer viewer;
8275b9b85e73SStefano Zampini     char filename[256];
8276b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8277b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
82786a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8279b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8280f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8281b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8282b9b85e73SStefano Zampini   }
8283b9b85e73SStefano Zampini #endif
8284f9eb5b7dSStefano Zampini 
828598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
828698a51de6SStefano Zampini     Vec crhs,csol;
828704708bb6SStefano Zampini 
8288f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8289f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8290f347579bSStefano Zampini     if (!csol) {
82912a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8292f9eb5b7dSStefano Zampini     }
8293f347579bSStefano Zampini     if (!crhs) {
82942a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8295f347579bSStefano Zampini     }
8296b0f5fe93SStefano Zampini   }
82971ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8298b0f5fe93SStefano Zampini 
8299b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8300b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8301b0f5fe93SStefano Zampini 
8302b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
83034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
83044f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
83054f1b2e48SStefano Zampini     }
8306b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8307b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8308b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8309b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8310b0f5fe93SStefano Zampini     if (coarse_mat) {
8311b0f5fe93SStefano Zampini       Vec         nullv;
8312b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8313b0f5fe93SStefano Zampini       PetscInt    nl;
8314b0f5fe93SStefano Zampini 
8315b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8316b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8317b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8318b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8319b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8320b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8321b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8322b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8323b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8324b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8325b0f5fe93SStefano Zampini     }
8326b0f5fe93SStefano Zampini   }
832743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8328b0f5fe93SStefano Zampini 
832943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8330b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8331b0f5fe93SStefano Zampini     PetscBool ispreonly;
8332b0f5fe93SStefano Zampini 
8333b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8334b0f5fe93SStefano Zampini       PetscBool isnull;
8335b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8336bef83e63SStefano Zampini       if (isnull) {
8337b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8338b0f5fe93SStefano Zampini       }
8339bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8340b0f5fe93SStefano Zampini     }
8341b0f5fe93SStefano Zampini     /* setup coarse ksp */
8342b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8343cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8344cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
83456e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8346c8587f34SStefano Zampini       KSP       check_ksp;
83472b510759SStefano Zampini       KSPType   check_ksp_type;
8348c8587f34SStefano Zampini       PC        check_pc;
83496e683305SStefano Zampini       Vec       check_vec,coarse_vec;
83506a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
83512b510759SStefano Zampini       PetscInt  its;
83526e683305SStefano Zampini       PetscBool compute_eigs;
83536e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
83546e683305SStefano Zampini       PetscInt  neigs;
83558e185a42SStefano Zampini       const char *prefix;
8356c8587f34SStefano Zampini 
83572b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
83586e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
8359*399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
836023ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8361f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8362e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8363e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8364e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
83652b510759SStefano Zampini       if (ispreonly) {
83662b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
83676e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
83682b510759SStefano Zampini       } else {
8369cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
83706e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8371c8587f34SStefano Zampini       }
8372c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
83736e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
83746e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
83756e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8376a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8377a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8378a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8379a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8380c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8381c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8382c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8383c8587f34SStefano Zampini       /* create random vec */
83842701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8385c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
83866e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8387c8587f34SStefano Zampini       /* solve coarse problem */
83886e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8389cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
83906e683305SStefano Zampini       if (compute_eigs) {
8391854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8392854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
83936e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
83941ae86dd6SStefano Zampini         if (neigs) {
83956e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
83966e683305SStefano Zampini           lambda_min = eigs_r[0];
83976e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
83982701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
83992701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8400cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8401cbcc2c2aSStefano Zampini             }
8402c8587f34SStefano Zampini           }
8403c8587f34SStefano Zampini         }
84041ae86dd6SStefano Zampini       }
8405cbcc2c2aSStefano Zampini 
8406c8587f34SStefano Zampini       /* check coarse problem residual error */
84076e683305SStefano Zampini       if (pcbddc->dbg_flag) {
84086e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
84096e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
84106e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8411c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
84126e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
84136e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8414779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
84156e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
84166e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
84176e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
84186e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8419b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8420b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8421b0f5fe93SStefano Zampini         }
84226e683305SStefano Zampini         if (compute_eigs) {
84236e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8424b03ebc13SStefano Zampini           KSPConvergedReason reason;
8425deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8426c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8427b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
84286e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8429b03ebc13SStefano 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);
84306e683305SStefano Zampini           for (i=0;i<neigs;i++) {
84316e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8432c8587f34SStefano Zampini           }
84336e683305SStefano Zampini         }
84346e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
84356e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
84366e683305SStefano Zampini       }
8437e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
84382701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8439c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
84406e683305SStefano Zampini       if (compute_eigs) {
84416e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
84426e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8443c8587f34SStefano Zampini       }
84446e683305SStefano Zampini     }
84456e683305SStefano Zampini   }
8446bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8447cbcc2c2aSStefano Zampini   /* print additional info */
8448cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
84496e683305SStefano Zampini     /* waits until all processes reaches this point */
84506e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
8451cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
8452cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8453cbcc2c2aSStefano Zampini   }
8454cbcc2c2aSStefano Zampini 
84552b510759SStefano Zampini   /* free memory */
8456fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
845743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8458c8587f34SStefano Zampini   PetscFunctionReturn(0);
8459c8587f34SStefano Zampini }
8460674ae819SStefano Zampini 
8461f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8462f34684f1SStefano Zampini {
8463f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8464f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8465f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8466dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8467dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
846873be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8469dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8470f34684f1SStefano Zampini   PetscErrorCode ierr;
8471f34684f1SStefano Zampini 
8472f34684f1SStefano Zampini   PetscFunctionBegin;
8473f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
84746c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8475dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
84763bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8477dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8478dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
84796583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8480dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8481dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8482dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
84836c4ed002SBarry 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);
8484dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8485dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8486dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8487dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8488dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8489f34684f1SStefano Zampini 
8490f34684f1SStefano Zampini   /* check numbering */
8491f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8492019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8493dc456d91SStefano Zampini     PetscInt    i;
8494b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8495f34684f1SStefano Zampini 
8496f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8497f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8498f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
84991575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8500019a44ceSStefano Zampini     /* counter */
8501019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8502019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8503019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8504019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8505019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8506019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8507f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8508f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8509727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8510f34684f1SStefano Zampini     }
8511f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8512f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8513f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8514e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8515e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8516e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8517e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8518f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8519019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8520f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8521019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
85222c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
852375c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8524b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
85252c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
85262c66d082SStefano 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);
8527f34684f1SStefano Zampini       }
8528f34684f1SStefano Zampini     }
8529019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8530b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8531f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8532f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8533f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8534f34684f1SStefano Zampini     }
8535f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8536f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8537e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8538e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8539f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8540f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8541b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8542ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8543ca8b9ea9SStefano Zampini 
8544ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
85453bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8546f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8547f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8548f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8549f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
85504bc2dc4bSStefano 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);
8551f34684f1SStefano Zampini       }
8552f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8553ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8554f34684f1SStefano Zampini     }
8555f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
85561575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8557302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8558f34684f1SStefano Zampini   }
85598bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8560f34684f1SStefano Zampini   /* get back data */
8561f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8562f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8563674ae819SStefano Zampini   PetscFunctionReturn(0);
8564674ae819SStefano Zampini }
8565674ae819SStefano Zampini 
8566a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8567e456f2a8SStefano Zampini {
8568e456f2a8SStefano Zampini   IS             localis_t;
8569a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8570e456f2a8SStefano Zampini   PetscScalar    *vals;
8571e456f2a8SStefano Zampini   PetscErrorCode ierr;
8572e456f2a8SStefano Zampini 
8573e456f2a8SStefano Zampini   PetscFunctionBegin;
8574a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8575e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8576854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8577e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8578e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8579a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8580a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
85811035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
85823151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8583a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
85841035eff8SStefano Zampini   }
8585a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8586e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8587e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8588a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8589a7dc3881SStefano Zampini   /* now compute set in local ordering */
8590a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8591a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8592a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8593a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8594a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8595ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8596e456f2a8SStefano Zampini       lsize++;
8597e456f2a8SStefano Zampini     }
8598e456f2a8SStefano Zampini   }
8599854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8600a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8601ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8602e456f2a8SStefano Zampini       idxs[lsize++] = i;
8603e456f2a8SStefano Zampini     }
8604e456f2a8SStefano Zampini   }
8605a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8606a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8607e456f2a8SStefano Zampini   *localis = localis_t;
8608e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8609e456f2a8SStefano Zampini }
8610906d46d4SStefano Zampini 
861108122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8612b96c3477SStefano Zampini {
8613a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8614b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8615b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8616a64f4aa4SStefano Zampini   Mat                 S_j;
8617b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8618b96c3477SStefano Zampini   PetscBool           free_used_adj;
8619b96c3477SStefano Zampini   PetscErrorCode      ierr;
8620b96c3477SStefano Zampini 
8621b96c3477SStefano Zampini   PetscFunctionBegin;
862243371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8623b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8624b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
862508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8626b96c3477SStefano Zampini     used_xadj = NULL;
8627b96c3477SStefano Zampini     used_adjncy = NULL;
8628b96c3477SStefano Zampini   } else {
862908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
863008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
863108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
863208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8633b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8634b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8635b96c3477SStefano Zampini     } else {
86362fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8637b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8638b96c3477SStefano Zampini       PetscInt       nvtxs;
8639b96c3477SStefano Zampini 
86402fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
86412fffb893SStefano Zampini       if (flg_row) {
8642b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8643b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8644b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8645b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
86462fffb893SStefano Zampini       } else {
86472fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
86482fffb893SStefano Zampini         used_xadj = NULL;
86492fffb893SStefano Zampini         used_adjncy = NULL;
86502fffb893SStefano Zampini       }
86512fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8652b96c3477SStefano Zampini     }
8653b96c3477SStefano Zampini   }
8654d5574798SStefano Zampini 
8655d5574798SStefano Zampini   /* setup sub_schurs data */
8656a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8657df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8658df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8659a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
866091af6908SStefano 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);
8661a64f4aa4SStefano Zampini   } else {
866272b8c272SStefano Zampini     Mat       change = NULL;
86639d54b7f4SStefano Zampini     Vec       scaling = NULL;
8664111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8665111315fdSstefano_zampini     PetscInt  benign_n;
8666111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8667111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8668111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8669a3df083aSStefano Zampini 
86705feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
86715feab87aSStefano Zampini       PetscInt n_vertices;
86725feab87aSStefano Zampini 
86735feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
86742034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
86755feab87aSStefano Zampini     }
867604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
867704708bb6SStefano Zampini     if (!isseqaij) {
867804708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
867904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
868004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
868104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
868204708bb6SStefano Zampini       } else {
8683511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
868404708bb6SStefano Zampini       }
868504708bb6SStefano Zampini     }
8686a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8687a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8688ca92afb2SStefano Zampini     } else {
8689a3df083aSStefano Zampini       benign_n = 0;
8690ca92afb2SStefano Zampini     }
8691b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8692b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8693b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
869472b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
869522db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8696b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
869722db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8698b7ab4a40SStefano Zampini     }
8699b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8700b7ab4a40SStefano 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 */
8701b7ab4a40SStefano Zampini     if (need_change) {
870288c03ad3SStefano Zampini       PC_IS   *pcisf;
870388c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
870488c03ad3SStefano Zampini       PC      pcf;
870588c03ad3SStefano Zampini 
8706e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
870788c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
870888c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
870988c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8710b9be95fcSstefano_zampini 
871188c03ad3SStefano Zampini       /* hacks */
871288c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
871372b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
871472b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
871572b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
871672b8c272SStefano Zampini       pcisf->n                     = pcis->n;
871772b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
871888c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
871988c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
872088c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
872188c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
872288c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
872388c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
872472b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
872588c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8726b9be95fcSstefano_zampini 
8727b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
872888c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
872972b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
873072b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
873172b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
873272b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8733b9be95fcSstefano_zampini 
873488c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
873572b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
873688c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
873788c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
873888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
873988c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
874088c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
874188c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8742b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
874388c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
874488c03ad3SStefano Zampini     }
87459d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8746111315fdSstefano_zampini 
8747111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8748111315fdSstefano_zampini     if (iP) {
8749111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8750111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8751111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8752111315fdSstefano_zampini     }
8753111315fdSstefano_zampini     if (discrete_harmonic) {
8754111315fdSstefano_zampini       Mat A;
8755111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8756111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8757111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8758111315fdSstefano_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);
8759111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8760111315fdSstefano_zampini     } else {
876191af6908SStefano 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);
8762111315fdSstefano_zampini     }
876372b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
876472b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8765ca92afb2SStefano Zampini   }
8766d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8767b96c3477SStefano Zampini 
8768b96c3477SStefano Zampini   /* free adjacency */
8769b96c3477SStefano Zampini   if (free_used_adj) {
8770b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8771b96c3477SStefano Zampini   }
877243371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8773b96c3477SStefano Zampini   PetscFunctionReturn(0);
8774b96c3477SStefano Zampini }
8775b96c3477SStefano Zampini 
877608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8777b96c3477SStefano Zampini {
8778b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8779b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8780b96c3477SStefano Zampini   PCBDDCGraph         graph;
8781b96c3477SStefano Zampini   PetscErrorCode      ierr;
8782b96c3477SStefano Zampini 
8783b96c3477SStefano Zampini   PetscFunctionBegin;
8784b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
878508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
87863301b35fSStefano Zampini     IS       verticesIS,verticescomm;
87873301b35fSStefano Zampini     PetscInt vsize,*idxs;
8788b96c3477SStefano Zampini 
8789b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
87903301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
87913301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
87923301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
87933301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8794c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8795b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8796be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8797441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
87983301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8799b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8800b96c3477SStefano Zampini   } else {
8801b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8802b96c3477SStefano Zampini   }
8803e4d548c7SStefano Zampini   /* print some info */
88045c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8805e4d548c7SStefano Zampini     IS       vertices;
8806e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8807c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8808e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8809e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8810e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8811e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8812e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8813e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8814e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8815e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8816e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8817c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8818e4d548c7SStefano Zampini   }
8819b96c3477SStefano Zampini 
8820b96c3477SStefano Zampini   /* sub_schurs init */
8821b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8822b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8823b334f244SStefano Zampini   }
882488113c35SStefano 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);
8825a64f4aa4SStefano Zampini 
8826b96c3477SStefano Zampini   /* free graph struct */
882708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8828b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8829b96c3477SStefano Zampini   }
8830b96c3477SStefano Zampini   PetscFunctionReturn(0);
8831b96c3477SStefano Zampini }
8832fa34dd3eSStefano Zampini 
8833fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8834fa34dd3eSStefano Zampini {
8835fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8836fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8837fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8838fa34dd3eSStefano Zampini 
8839fa34dd3eSStefano Zampini   PetscFunctionBegin;
8840fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8841fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
88424f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8843fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
88444f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
884575c01103SStefano Zampini     PetscReal      norm;
8846fa34dd3eSStefano Zampini     PetscInt       i;
8847fa34dd3eSStefano Zampini 
8848fa34dd3eSStefano Zampini     /* B0 and B0_B */
8849fa34dd3eSStefano Zampini     if (zerodiag) {
8850fa34dd3eSStefano Zampini       IS       dummy;
8851fa34dd3eSStefano Zampini 
88524f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
88537dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8854fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8855fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8856fa34dd3eSStefano Zampini     }
8857fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8858fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8859fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8860fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8861fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8862fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8863fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8864fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8865fa34dd3eSStefano Zampini     /* S_j */
8866fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8867fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8868fa34dd3eSStefano Zampini 
8869fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8870fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8871fa34dd3eSStefano Zampini     /* continuous in primal space */
8872fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8873fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8874fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8875fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
88764f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
88774f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8878fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8879fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8880fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8881fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8882fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8883fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8884fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8885fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8886fa34dd3eSStefano Zampini 
8887fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8888fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8889fa34dd3eSStefano Zampini     /* local with Schur */
8890fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8891fa34dd3eSStefano Zampini     if (zerodiag) {
8892fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
88934f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8894fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8895fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8896fa34dd3eSStefano Zampini     }
8897fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8898fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8899fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8900fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8901fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8902fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8903fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8904fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8905fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8906fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8907fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8908fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8909fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8910fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8911fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8912fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8913fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8914fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8915fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8916fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8917fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8918fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8919fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8920fa34dd3eSStefano Zampini     if (zerodiag) {
8921fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8922fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
89234f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8924fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8925fa34dd3eSStefano Zampini     }
8926fa34dd3eSStefano Zampini     /* BDDC */
8927fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8928fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8929fa34dd3eSStefano Zampini 
8930fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8931fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8932fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8933fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
89344f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
89354f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8936fa34dd3eSStefano Zampini     }
89374f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8938fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8939fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8940fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8941fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8942fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8943fa34dd3eSStefano Zampini   }
8944fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8945fa34dd3eSStefano Zampini }
89461e0482f5SStefano Zampini 
89471e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
89481e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
89491e0482f5SStefano Zampini {
89501e0482f5SStefano Zampini   Mat            At;
89511e0482f5SStefano Zampini   IS             rows;
89521e0482f5SStefano Zampini   PetscInt       rst,ren;
89531e0482f5SStefano Zampini   PetscErrorCode ierr;
89541e0482f5SStefano Zampini   PetscLayout    rmap;
89551e0482f5SStefano Zampini 
89561e0482f5SStefano Zampini   PetscFunctionBegin;
89571e0482f5SStefano Zampini   rst = ren = 0;
89581e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
89591e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
89601e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
89611e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
89621e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
89631e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
89641e0482f5SStefano Zampini   }
8965e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
89667dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
89671e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
89681e0482f5SStefano Zampini 
89691e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
89701e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
89711e0482f5SStefano Zampini     IS         from,to;
89721e0482f5SStefano Zampini     Vec        gvec;
89731e0482f5SStefano Zampini     PetscInt   lsize;
89741e0482f5SStefano Zampini 
89751e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
89761e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
89771e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
89781e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
89791e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
89801e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
89811e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
89821e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
89831e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
89841e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
89851e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
89861e0482f5SStefano Zampini     b->A = a->A;
89871e0482f5SStefano Zampini     b->B = a->B;
89881e0482f5SStefano Zampini 
89891e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
89901e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
89911e0482f5SStefano Zampini     b->rowindices      = 0;
89921e0482f5SStefano Zampini     b->rowvalues       = 0;
89931e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
89941e0482f5SStefano Zampini 
89951e0482f5SStefano Zampini     (*B)->rmap         = rmap;
89961e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
89971e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
89981e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
89991e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
90001e0482f5SStefano Zampini 
90011e0482f5SStefano Zampini     if (a->colmap) {
90021e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
90031e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
90041e0482f5SStefano Zampini #else
90051e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
90061e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90071e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
90081e0482f5SStefano Zampini #endif
90091e0482f5SStefano Zampini     } else b->colmap = 0;
90101e0482f5SStefano Zampini     if (a->garray) {
90111e0482f5SStefano Zampini       PetscInt len;
90121e0482f5SStefano Zampini       len  = a->B->cmap->n;
90131e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
90141e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
90151e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
90161e0482f5SStefano Zampini     } else b->garray = 0;
90171e0482f5SStefano Zampini 
90181e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
90191e0482f5SStefano Zampini     b->lvec = a->lvec;
90201e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
90211e0482f5SStefano Zampini 
90221e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
90231e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
90241e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
90251e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
90261e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
90271e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
90281e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
90291e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
90301e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
90311e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
90321e0482f5SStefano Zampini   }
90331e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
90341e0482f5SStefano Zampini   PetscFunctionReturn(0);
90351e0482f5SStefano Zampini }
9036