xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision ab2d12f3aa8d72f387ac451c7fe18daf4873bbad)
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   PetscScalar    *uwork,*data,*U, ds = 0.;
18a13144ffSStefano Zampini   PetscReal      *sing;
19a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
20a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
21a13144ffSStefano Zampini   PetscErrorCode ierr;
22abee2b68SSebastian Grimberg #if defined(PETSC_USE_COMPLEX)
23abee2b68SSebastian Grimberg   PetscReal      *rwork2;
24abee2b68SSebastian Grimberg #endif
25a13144ffSStefano Zampini 
26a13144ffSStefano Zampini   PetscFunctionBegin;
27a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
28a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
29a13144ffSStefano Zampini 
30a13144ffSStefano Zampini   /* workspace */
31a13144ffSStefano Zampini   if (!work) {
32a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
33f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
34a13144ffSStefano Zampini   } else {
35a13144ffSStefano Zampini     ulw   = lw;
36a13144ffSStefano Zampini     uwork = work;
37a13144ffSStefano Zampini   }
38a13144ffSStefano Zampini   n = PetscMin(nr,nc);
39a13144ffSStefano Zampini   if (!rwork) {
40a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
41a13144ffSStefano Zampini   } else {
42a13144ffSStefano Zampini     sing = rwork;
43a13144ffSStefano Zampini   }
44a13144ffSStefano Zampini 
45a13144ffSStefano Zampini   /* SVD */
46a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
47a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52abee2b68SSebastian Grimberg #if !defined(PETSC_USE_COMPLEX)
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54abee2b68SSebastian Grimberg #else
55abee2b68SSebastian Grimberg   ierr = PetscMalloc1(5*n,&rwork2);CHKERRQ(ierr);
56abee2b68SSebastian Grimberg   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,rwork2,&lierr));
57abee2b68SSebastian Grimberg   ierr = PetscFree(rwork2);CHKERRQ(ierr);
58abee2b68SSebastian Grimberg #endif
59a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
60a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
61a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
62a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
63a13144ffSStefano Zampini   if (!rwork) {
64a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
65a13144ffSStefano Zampini   }
66a13144ffSStefano Zampini   if (!work) {
67a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
68a13144ffSStefano Zampini   }
69a13144ffSStefano Zampini   /* create B */
70f498cd09SStefano Zampini   if (!range) {
71a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
72a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
73580bdb30SBarry Smith     ierr = PetscArraycpy(data,U+nr*i,(nr-i)*nr);CHKERRQ(ierr);
74f498cd09SStefano Zampini   } else {
75f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
76f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
77580bdb30SBarry Smith     ierr = PetscArraycpy(data,U,i*nr);CHKERRQ(ierr);
78f498cd09SStefano Zampini   }
79a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
80a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat               GEc;
1211683a169SBarry Smith     const PetscScalar *vals;
1221683a169SBarry Smith     PetscScalar       v;
1231e0482f5SStefano Zampini 
1247dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1261683a169SBarry Smith     ierr = MatDenseGetArrayRead(GEd,&vals);CHKERRQ(ierr);
127637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
128637e8532SStefano Zampini     v    = 1.;
1291e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1301e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1311683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(GEd,&vals);CHKERRQ(ierr);
1321e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1331e0482f5SStefano Zampini #if defined(PRINT_GDET)
1341e0482f5SStefano Zampini     {
1351e0482f5SStefano Zampini       PetscViewer viewer;
1361e0482f5SStefano Zampini       char filename[256];
1371e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1381e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1471e0482f5SStefano Zampini     }
1481e0482f5SStefano Zampini #endif
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1501e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1511e0482f5SStefano Zampini   }
1521e0482f5SStefano Zampini 
153a13144ffSStefano Zampini   PetscFunctionReturn(0);
154a13144ffSStefano Zampini }
155a13144ffSStefano Zampini 
156a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
157a13144ffSStefano Zampini {
158a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
159a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1600569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
161eee23b56SStefano Zampini   Vec                    tvec;
162a13144ffSStefano Zampini   PetscSF                sfv;
1631e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
164a13144ffSStefano Zampini   MPI_Comm               comm;
165c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
166c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1677d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
168a13144ffSStefano Zampini   PetscScalar            *vals,*work;
169a13144ffSStefano Zampini   PetscReal              *rwork;
170a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1711e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
172a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
173eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
174b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
175a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
176b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
177637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
180a13144ffSStefano Zampini   PetscErrorCode         ierr;
181a13144ffSStefano Zampini 
182a13144ffSStefano Zampini   PetscFunctionBegin;
183213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
184213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
185213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
186213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
187213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
188213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
189213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
190213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
191a13144ffSStefano Zampini   print      = PETSC_FALSE;
192213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
193a13144ffSStefano Zampini 
194213b8bfaSStefano Zampini   /* Command line customization */
195213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
196213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
200213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
201213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
202213b8bfaSStefano Zampini 
203213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2041e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2051e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
206213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   if (!singular) {
208a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
209a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
210c2151214SStefano Zampini     for (i=0;i<n;i++) {
211a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
212a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
213a13144ffSStefano Zampini         break;
214a13144ffSStefano Zampini       }
215a13144ffSStefano Zampini     }
216a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
217820f2d46SBarry Smith     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRMPI(ierr);
218a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
219213b8bfaSStefano Zampini   }
220a13144ffSStefano Zampini 
221213b8bfaSStefano Zampini   /* Get Nedelec field */
2226080607fSStefano 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);
223213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
224c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
225c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
226c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
227213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
228213b8bfaSStefano Zampini     ne            = n;
229213b8bfaSStefano Zampini     nedfieldlocal = NULL;
230213b8bfaSStefano Zampini     global        = PETSC_TRUE;
231213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
232213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
233213b8bfaSStefano Zampini 
234580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
235580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
236213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
237213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
238213b8bfaSStefano Zampini       PetscInt nc;
239213b8bfaSStefano Zampini 
240213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
241213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
242213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
243213b8bfaSStefano Zampini     }
244ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
245ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
246213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
248213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
249213b8bfaSStefano Zampini   } else {
250213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
251213b8bfaSStefano Zampini   }
252213b8bfaSStefano Zampini 
253213b8bfaSStefano Zampini   /* Sanity checks */
254213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
255213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
2566080607fSStefano 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);
257213b8bfaSStefano Zampini 
258213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2591e0482f5SStefano Zampini   if (setprimal) {
260eee23b56SStefano Zampini     IS       enedfieldlocal;
261eee23b56SStefano Zampini     PetscInt *eidxs;
262eee23b56SStefano Zampini 
263eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
264eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
265213b8bfaSStefano Zampini     if (nedfieldlocal) {
266213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
267eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
268eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
269eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
270eee23b56SStefano Zampini         }
271eee23b56SStefano Zampini       }
272eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
273213b8bfaSStefano Zampini     } else {
274213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
275213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
276213b8bfaSStefano Zampini           eidxs[cum++] = i;
277213b8bfaSStefano Zampini         }
278213b8bfaSStefano Zampini       }
279213b8bfaSStefano Zampini     }
280213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
281eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
282eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2841e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
285eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     PetscFunctionReturn(0);
2871e0482f5SStefano Zampini   }
288a13144ffSStefano Zampini 
289213b8bfaSStefano Zampini   /* Compute some l2g maps */
290213b8bfaSStefano Zampini   if (nedfieldlocal) {
291c2151214SStefano Zampini     IS is;
292c2151214SStefano Zampini 
293c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
294c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2951e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2961e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
2981e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
2991e0482f5SStefano Zampini     if (global) {
3001e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3011e0482f5SStefano Zampini       el2g = al2g;
3021e0482f5SStefano Zampini     } else {
3031e0482f5SStefano Zampini       IS gis;
3041e0482f5SStefano Zampini 
3051e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3061e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3071e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3081e0482f5SStefano Zampini     }
309c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
310c2151214SStefano Zampini   } else {
3111e0482f5SStefano Zampini     /* restore default */
3121e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3131e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3141e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3151e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3161e0482f5SStefano Zampini     el2g = al2g;
317c2151214SStefano Zampini     fl2g = NULL;
318c2151214SStefano Zampini   }
319a13144ffSStefano Zampini 
320213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
321580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
322580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
323c2151214SStefano Zampini   if (nedfieldlocal) {
324c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
325c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
326c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini   } else {
328c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
329c2151214SStefano Zampini   }
330c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
331c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
332213b8bfaSStefano Zampini 
333213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
334213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
335213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3361e0482f5SStefano Zampini     if (global) {
3371e0482f5SStefano Zampini       PetscInt rst;
3381e0482f5SStefano Zampini 
339c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
340c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
341c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
342c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
343c2151214SStefano Zampini         }
344c2151214SStefano Zampini       }
345a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
346c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3471e0482f5SStefano Zampini     } else {
3481e0482f5SStefano Zampini       PetscInt *tbz;
3491e0482f5SStefano Zampini 
3501e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
351ad227feaSJunchao Zhang       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
352ad227feaSJunchao Zhang       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3551e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3561e0482f5SStefano Zampini           tbz[cum++] = i;
3571e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3581e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3591e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini     }
362213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
363213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
364213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
365213b8bfaSStefano Zampini   }
366a13144ffSStefano Zampini 
367a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
368a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
369a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3707dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
372a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
376a13144ffSStefano Zampini 
377213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
378c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
379a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
380a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
386213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
387213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
388a13144ffSStefano Zampini 
3891e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
390213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
391a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
392213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
393a13144ffSStefano Zampini 
394213b8bfaSStefano Zampini   if (print) {
395213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
396213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
397213b8bfaSStefano Zampini   }
398213b8bfaSStefano Zampini 
399213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4000569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4010569b399SStefano Zampini 
402a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4034e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4044e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
405a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
406a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4087d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
409c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
410a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
411a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
412a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
413c2151214SStefano Zampini     IS is;
414c2151214SStefano Zampini 
415c2151214SStefano Zampini     if (fl2g) {
416c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
417c2151214SStefano Zampini     } else {
418c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
419c2151214SStefano Zampini     }
420c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
421c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
422a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
423a13144ffSStefano Zampini       if (idxs[i] >= 0) {
424a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4257d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
426a13144ffSStefano Zampini       }
427a13144ffSStefano Zampini     }
428c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
429c2151214SStefano Zampini     if (fl2g) {
430c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
431c2151214SStefano Zampini     }
432a13144ffSStefano Zampini   }
433a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
434c2151214SStefano Zampini     IS is;
435c2151214SStefano Zampini 
436c2151214SStefano Zampini     if (fl2g) {
437c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
438c2151214SStefano Zampini     } else {
439c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
440c2151214SStefano Zampini     }
441c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
442c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
443a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
444a13144ffSStefano Zampini       if (idxs[i] >= 0) {
445a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
446a13144ffSStefano Zampini       }
447a13144ffSStefano Zampini     }
448c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
449c2151214SStefano Zampini     if (fl2g) {
450c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
451a13144ffSStefano Zampini     }
452c2151214SStefano Zampini   }
453c2151214SStefano Zampini 
454213b8bfaSStefano Zampini   /* Count neighs per dof */
455b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
456b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
457637e8532SStefano Zampini 
4587d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4597d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
46062b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
46162b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
462b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
46362b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
46462b0c6f7SStefano Zampini     }
46562b0c6f7SStefano Zampini   }
466637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
46762b0c6f7SStefano Zampini   if (!conforming) {
46862b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
46962b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
47062b0c6f7SStefano Zampini   }
4714e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
472dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
47362b0c6f7SStefano Zampini   cum  = 0;
474a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
475dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47662b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
477a13144ffSStefano Zampini       marks[cum++] = i;
478dec27d64SStefano Zampini       continue;
479dec27d64SStefano Zampini     }
480dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
48162b0c6f7SStefano Zampini     if (!conforming) {
48262b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
483a13144ffSStefano Zampini         marks[cum++] = i;
484a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
485a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
486a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
487a13144ffSStefano Zampini         }
48862b0c6f7SStefano Zampini       } else {
48962b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
49062b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
49162b0c6f7SStefano Zampini            - at most 2 endpoints
49262b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49362b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49462b0c6f7SStefano Zampini         */
49562b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49662b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49762b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
49862b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
49962b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
50062b0c6f7SStefano Zampini           if (nconn > order) ends++;
50162b0c6f7SStefano Zampini           else if (nconn == order) ints++;
50262b0c6f7SStefano Zampini           else undef++;
50362b0c6f7SStefano Zampini         }
50462b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50562b0c6f7SStefano Zampini           marks[cum++] = i;
50662b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
50762b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
50862b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
50962b0c6f7SStefano Zampini           }
51062b0c6f7SStefano Zampini         }
51162b0c6f7SStefano Zampini       }
512a13144ffSStefano Zampini     }
513dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
514dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
515dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
516dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
517a13144ffSStefano Zampini     }
518dec27d64SStefano Zampini   }
51962b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
520dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5214e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
52262b0c6f7SStefano Zampini   if (!conforming) {
52362b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52462b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
52562b0c6f7SStefano Zampini   }
5264e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
527637e8532SStefano Zampini 
528b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5294e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
530a13144ffSStefano Zampini   if (print) {
5314e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5324e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5334e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
534a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
535a13144ffSStefano Zampini   }
536a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
537dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
538a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
539637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5407d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
541b03ebc13SStefano Zampini     if (!order) { /* variable order */
542dec27d64SStefano Zampini       PetscReal vorder = 0.;
543dec27d64SStefano Zampini 
544dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
545dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
5466080607fSStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%D)",vorder,test);
547dec27d64SStefano Zampini       ord  = 1;
548dec27d64SStefano Zampini     }
549cf9c20a2SJed Brown     if (PetscUnlikelyDebug(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);
550637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5517d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5527d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5537d871cd7SStefano Zampini         break;
5547d871cd7SStefano Zampini       }
555637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
556637e8532SStefano Zampini         sneighs = PETSC_FALSE;
557637e8532SStefano Zampini       } else {
558637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
559637e8532SStefano Zampini         for (k=0;k<vc;k++) {
560637e8532SStefano Zampini           if (vn[k] != en[k]) {
561637e8532SStefano Zampini             sneighs = PETSC_FALSE;
562637e8532SStefano Zampini             break;
563637e8532SStefano Zampini           }
564637e8532SStefano Zampini         }
565637e8532SStefano Zampini       }
566637e8532SStefano Zampini     }
5677d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5686080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %D (%D %D %D)\n",i,!sneighs,test >= 3*ord,bdir);
569a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
570dec27d64SStefano Zampini     } else if (test == ord) {
571b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
5726080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %D\n",i);
573a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
574a13144ffSStefano Zampini       } else {
5756080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %D\n",i);
576a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
577a13144ffSStefano Zampini       }
578a13144ffSStefano Zampini     }
579a13144ffSStefano Zampini   }
580b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs);CHKERRQ(ierr);
581b63b1311SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs);CHKERRQ(ierr);
5827d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
583b03ebc13SStefano Zampini 
584b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
585b03ebc13SStefano Zampini   if (order != 1) {
586b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
587b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
588b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
589b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
590b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
591b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
592b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
593b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
594b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
595b03ebc13SStefano Zampini             PetscInt v = jjt[k];
596b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
597b03ebc13SStefano Zampini               found = PETSC_TRUE;
598b03ebc13SStefano Zampini               break;
599b03ebc13SStefano Zampini             }
600b03ebc13SStefano Zampini           }
601b03ebc13SStefano Zampini         }
602b03ebc13SStefano Zampini         if (!found) {
6036080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D CLEARED\n",i);
604b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
605b03ebc13SStefano Zampini         } else {
6066080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %D ACCEPTED\n",i);
607b03ebc13SStefano Zampini         }
608b03ebc13SStefano Zampini       }
609b03ebc13SStefano Zampini     }
610b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
611b03ebc13SStefano Zampini   }
612dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
613a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
614b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
615a13144ffSStefano Zampini 
616a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6170569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
618a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6194e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
620a13144ffSStefano Zampini 
6214e64d54eSstefano_zampini   /* Mark interior nodal dofs */
622a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6234e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
624a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
625a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6264e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
627a13144ffSStefano Zampini     }
628a13144ffSStefano Zampini   }
629a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
630a13144ffSStefano Zampini 
631a13144ffSStefano Zampini   /* communicate corners and splitpoints */
632a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
633580bdb30SBarry Smith   ierr = PetscArrayzero(sfvleaves,nv);CHKERRQ(ierr);
634580bdb30SBarry Smith   ierr = PetscArrayzero(sfvroots,Lv);CHKERRQ(ierr);
635a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
636a13144ffSStefano Zampini 
637a13144ffSStefano Zampini   if (print) {
638a13144ffSStefano Zampini     IS tbz;
639a13144ffSStefano Zampini 
640a13144ffSStefano Zampini     cum = 0;
641a13144ffSStefano Zampini     for (i=0;i<nv;i++)
642a13144ffSStefano Zampini       if (sfvleaves[i])
643a13144ffSStefano Zampini         vmarks[cum++] = i;
644a13144ffSStefano Zampini 
645a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
646a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
647a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
648a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
649a13144ffSStefano Zampini   }
650a13144ffSStefano Zampini 
651a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
652a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
653ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE);CHKERRQ(ierr);
654ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE);CHKERRQ(ierr);
655a13144ffSStefano Zampini 
6564e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6574e64d54eSstefano_zampini      and interior nodal dofs */
658a13144ffSStefano Zampini   cum = 0;
659a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
660a13144ffSStefano Zampini     if (sfvleaves[i]) {
661a13144ffSStefano Zampini       vmarks[cum++] = i;
662a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
663a13144ffSStefano Zampini     }
6644e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
665a13144ffSStefano Zampini   }
6664e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
667a13144ffSStefano Zampini   if (print) {
668a13144ffSStefano Zampini     IS tbz;
669a13144ffSStefano Zampini 
670a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6714e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
672a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
673a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
674a13144ffSStefano Zampini   }
675a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
676a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
677a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
678a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
679a13144ffSStefano Zampini 
680a13144ffSStefano Zampini   /* Recompute G */
681a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
682a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
683a13144ffSStefano Zampini   if (print) {
684a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
685a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
686a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
687a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
688a13144ffSStefano Zampini   }
689a13144ffSStefano Zampini 
690a13144ffSStefano Zampini   /* Get primal dofs (if any) */
691a13144ffSStefano Zampini   cum = 0;
692a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
693a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
694a13144ffSStefano Zampini   }
695c2151214SStefano Zampini   if (fl2g) {
696c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
697c2151214SStefano Zampini   }
698a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
699a13144ffSStefano Zampini   if (print) {
700a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
701a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
702a13144ffSStefano Zampini   }
703a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
704c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
705a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
706a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
707a13144ffSStefano Zampini 
708a13144ffSStefano Zampini   /* Compute edge connectivity */
709a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
7104222ddf1SHong Zhang 
7114222ddf1SHong Zhang   /* Symbolic conn = lG*lGt */
7124222ddf1SHong Zhang   ierr = MatProductCreate(lG,lGt,NULL,&conn);CHKERRQ(ierr);
7134222ddf1SHong Zhang   ierr = MatProductSetType(conn,MATPRODUCT_AB);CHKERRQ(ierr);
7144222ddf1SHong Zhang   ierr = MatProductSetAlgorithm(conn,"default");CHKERRQ(ierr);
7154222ddf1SHong Zhang   ierr = MatProductSetFill(conn,PETSC_DEFAULT);CHKERRQ(ierr);
7164222ddf1SHong Zhang   ierr = PetscObjectSetOptionsPrefix((PetscObject)conn,"econn_");CHKERRQ(ierr);
7174222ddf1SHong Zhang   ierr = MatProductSetFromOptions(conn);CHKERRQ(ierr);
7184222ddf1SHong Zhang   ierr = MatProductSymbolic(conn);CHKERRQ(ierr);
7194222ddf1SHong Zhang 
720a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
721c2151214SStefano Zampini   if (fl2g) {
722c2151214SStefano Zampini     PetscBT   btf;
723c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
724c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
725c2151214SStefano Zampini 
726c2151214SStefano Zampini     /* create CSR for all local dofs */
727c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
728c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
7296080607fSStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %D. Should be %D",pcbddc->mat_graph->nvtxs_csr,n);
730c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
731c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
732c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
733c2151214SStefano Zampini       rest = PETSC_TRUE;
734c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
735c2151214SStefano Zampini     } else {
736c2151214SStefano Zampini       free   = PETSC_TRUE;
737c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
738c2151214SStefano Zampini       iiu[0] = 0;
739c2151214SStefano Zampini       for (i=0;i<n;i++) {
740c2151214SStefano Zampini         iiu[i+1] = i+1;
741c2151214SStefano Zampini         jju[i]   = -1;
742d904f53bSStefano Zampini       }
743c2151214SStefano Zampini     }
744c2151214SStefano Zampini 
745c2151214SStefano Zampini     /* import sizes of CSR */
746c2151214SStefano Zampini     iia[0] = 0;
747c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
748c2151214SStefano Zampini 
749c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
750c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
751c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
752c2151214SStefano Zampini     for (i=0;i<ne;i++) {
753c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
754c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
755c2151214SStefano Zampini     }
756c2151214SStefano Zampini 
757c2151214SStefano Zampini     /* iia in CSR */
758c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
759c2151214SStefano Zampini 
760c2151214SStefano Zampini     /* jja in CSR */
761c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
762c2151214SStefano Zampini     for (i=0;i<n;i++)
763c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
764c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
765c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
766c2151214SStefano Zampini 
767c2151214SStefano Zampini     /* map edge dofs connectivity */
7681e0482f5SStefano Zampini     if (jj) {
769c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
770c2151214SStefano Zampini       for (i=0;i<ne;i++) {
771c2151214SStefano Zampini         PetscInt e = idxs[i];
772c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
773c2151214SStefano Zampini       }
7741e0482f5SStefano Zampini     }
775c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
776c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
777c2151214SStefano Zampini     if (rest) {
778c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
779c2151214SStefano Zampini     }
780c2151214SStefano Zampini     if (free) {
781c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
782c2151214SStefano Zampini     }
783c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
784c2151214SStefano Zampini   } else {
785c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
786c2151214SStefano Zampini   }
787c2151214SStefano Zampini 
788a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
789a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
790213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
791a13144ffSStefano Zampini 
792a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
793c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
794a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
795a13144ffSStefano Zampini 
796c2151214SStefano Zampini   if (fl2g) {
797c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
798c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
799c2151214SStefano Zampini     for (i=0;i<nee;i++) {
800c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
801c2151214SStefano Zampini     }
802c2151214SStefano Zampini   } else {
803c2151214SStefano Zampini     eedges  = alleedges;
804c2151214SStefano Zampini     primals = allprimals;
805c2151214SStefano Zampini   }
806c2151214SStefano Zampini 
807a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
808580bdb30SBarry Smith   ierr = PetscArrayzero(marks,ne);CHKERRQ(ierr);
809c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
810c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
811c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
812c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
813c2151214SStefano Zampini   if (print) {
814c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
815c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
816c2151214SStefano Zampini   }
817c2151214SStefano Zampini 
818c2151214SStefano Zampini   maxsize = 0;
819a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
820a13144ffSStefano Zampini     PetscInt size,mark = i+1;
821a13144ffSStefano Zampini 
822a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
823a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
824a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
825a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
826a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
827a13144ffSStefano Zampini   }
828a13144ffSStefano Zampini 
829a13144ffSStefano Zampini   /* Find coarse edge endpoints */
830a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
831a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
832a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
833a13144ffSStefano Zampini     PetscInt mark = i+1,size;
834a13144ffSStefano Zampini 
835a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8361e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8376080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
838a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
839a13144ffSStefano Zampini     if (print) {
8406080607fSStefano Zampini       ierr = PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %D\n",i);CHKERRQ(ierr);
8416080607fSStefano Zampini       ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
842a13144ffSStefano Zampini     }
843a13144ffSStefano Zampini     for (j=0;j<size;j++) {
844a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
8456080607fSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %D\n",ee);
846a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8476080607fSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %D\n",jj[k]);
848a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
8496080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %D\n",jj[k]);
850a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
851a13144ffSStefano Zampini           PetscInt  k2;
852a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
853a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
8546080607fSStefano 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]));
855c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
856c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
857c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
858a13144ffSStefano Zampini               corner = PETSC_TRUE;
859a13144ffSStefano Zampini               break;
860a13144ffSStefano Zampini             }
861a13144ffSStefano Zampini           }
862a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
8636080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %D\n",jj[k]);
864a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
865a13144ffSStefano Zampini           } else {
866a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
867a13144ffSStefano Zampini           }
868a13144ffSStefano Zampini         }
869a13144ffSStefano Zampini       }
870a13144ffSStefano Zampini     }
871a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
872a13144ffSStefano Zampini   }
873a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
874a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
875c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
876a13144ffSStefano Zampini 
877a13144ffSStefano Zampini   /* Reset marked primal dofs */
878a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
879a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
880a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
881a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
882a13144ffSStefano Zampini 
8830569b399SStefano Zampini   /* Now use the initial lG */
8840569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8850569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8860569b399SStefano Zampini   lG   = lGinit;
8870569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8880569b399SStefano Zampini 
889a13144ffSStefano Zampini   /* Compute extended cols indices */
890b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
891b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
892a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
893a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
894a13144ffSStefano Zampini   i   *= maxsize;
895b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
896a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
897a13144ffSStefano Zampini   eerr = PETSC_FALSE;
898a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
899b03ebc13SStefano Zampini     PetscInt size,found = 0;
900a13144ffSStefano Zampini 
901a13144ffSStefano Zampini     cum  = 0;
902a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9031e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9046080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
905a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
906b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
907a13144ffSStefano Zampini     for (j=0;j<size;j++) {
908a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
909b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
910b03ebc13SStefano Zampini         PetscInt vv = jj[k];
911b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
912b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
913b03ebc13SStefano Zampini       }
914a13144ffSStefano Zampini     }
915a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
916a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
917a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
918a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
919a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
920a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
921a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
922b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
923b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
924a13144ffSStefano Zampini       if (print) {
925a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
926a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
927a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
928a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
929a13144ffSStefano Zampini       }
930a13144ffSStefano Zampini       eerr = PETSC_TRUE;
931a13144ffSStefano Zampini     }
932a13144ffSStefano Zampini   }
9334e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
934820f2d46SBarry Smith   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRMPI(ierr);
935a13144ffSStefano Zampini   if (done) {
936a13144ffSStefano Zampini     PetscInt *newprimals;
937a13144ffSStefano Zampini 
938a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
939a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
940a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
941580bdb30SBarry Smith     ierr = PetscArraycpy(newprimals,idxs,cum);CHKERRQ(ierr);
942a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9430569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
9446080607fSStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %D)\n",eerr);
945a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
946b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
947b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
948a13144ffSStefano Zampini         PetscInt size,mark = i+1;
949a13144ffSStefano Zampini 
950a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
951a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
952c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
953a13144ffSStefano Zampini         for (j=0;j<size;j++) {
954a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
9556080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %D [%D %D)\n",ee,ii[ee],ii[ee+1]);
956a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
957a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
958a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
959a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
960b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
9616080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %D\n",vv);
962a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
963a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
964a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
965a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
966a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
9676080607fSStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %D\n",ee2);
968a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
969a13144ffSStefano Zampini                   /* finally set the new corners */
970a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
9716080607fSStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %D\n",jj[k3]);
972a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
973a13144ffSStefano Zampini                   }
974a13144ffSStefano Zampini                 }
975a13144ffSStefano Zampini               }
976b03ebc13SStefano Zampini             } else {
9776080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %D\n",jj[k]);
978a13144ffSStefano Zampini             }
979a13144ffSStefano Zampini           }
980a13144ffSStefano Zampini         }
981b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
982b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
983b03ebc13SStefano Zampini 
984b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
9856080607fSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %D\n",i);
986b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
987b03ebc13SStefano Zampini             PetscInt k2;
9886080607fSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %D\n",jj[k]);
989b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
990b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
991b03ebc13SStefano Zampini           }
992b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
993b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
9946080607fSStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %D\n",idxs[j]);
995b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
996b03ebc13SStefano Zampini             }
997b03ebc13SStefano Zampini           }
998b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
999b03ebc13SStefano Zampini         }
1000a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1001a13144ffSStefano Zampini       }
1002a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1003a13144ffSStefano Zampini     }
1004b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10050569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1006a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1007c2151214SStefano Zampini     if (fl2g) {
1008c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1009c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1010c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1011c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1012c2151214SStefano Zampini       }
1013c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1014c2151214SStefano Zampini     }
1015c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1016a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1017a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1018a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1019a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1020a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1021213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1022c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1023c2151214SStefano Zampini     if (fl2g) {
1024c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1025c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1026c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1027c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1028c2151214SStefano Zampini       }
1029c2151214SStefano Zampini     } else {
1030c2151214SStefano Zampini       eedges  = alleedges;
1031c2151214SStefano Zampini       primals = allprimals;
1032c2151214SStefano Zampini     }
1033b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1034a13144ffSStefano Zampini 
1035a13144ffSStefano Zampini     /* Mark again */
1036580bdb30SBarry Smith     ierr = PetscArrayzero(marks,ne);CHKERRQ(ierr);
1037a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1038a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1039a13144ffSStefano Zampini 
1040a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1041a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1042a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1043a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1044a13144ffSStefano Zampini     }
1045a13144ffSStefano Zampini     if (print) {
1046a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1047a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1048a13144ffSStefano Zampini     }
1049a13144ffSStefano Zampini 
1050a13144ffSStefano Zampini     /* Recompute extended cols */
1051a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1052a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1053a13144ffSStefano Zampini       PetscInt size;
1054a13144ffSStefano Zampini 
1055a13144ffSStefano Zampini       cum  = 0;
1056a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10571e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10586080607fSStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
1059a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1060a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1061a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10621e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1063a13144ffSStefano Zampini       }
1064a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1065a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1066a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1067a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1068a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1069a13144ffSStefano Zampini       if (cum != size -1) {
1070a13144ffSStefano Zampini         if (print) {
1071a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1072a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1073a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1074a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1075a13144ffSStefano Zampini         }
1076a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1077a13144ffSStefano Zampini       }
1078a13144ffSStefano Zampini     }
1079a13144ffSStefano Zampini   }
1080a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1081a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1082b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
10837d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1084a13144ffSStefano Zampini   /* an error should not occur at this point */
1085a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1086a13144ffSStefano Zampini 
10874e64d54eSstefano_zampini   /* Check the number of endpoints */
10880569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1089b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1090b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10914e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1092b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10934e64d54eSstefano_zampini 
1094b03ebc13SStefano Zampini     /* init with defaults */
1095b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10964e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10971e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10986080607fSStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i);
10994e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1100b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11014e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11024e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11034e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11044e64d54eSstefano_zampini         PetscInt vv = jj[k];
11054e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
11066080607fSStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %D",i);
1107b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11084e64d54eSstefano_zampini         }
11094e64d54eSstefano_zampini       }
11104e64d54eSstefano_zampini     }
1111b03ebc13SStefano Zampini     if (found != 2) {
1112b03ebc13SStefano Zampini       PetscInt e;
1113b03ebc13SStefano Zampini       if (fl2g) {
1114b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1115b03ebc13SStefano Zampini       } else {
1116b03ebc13SStefano Zampini         e = idxs[0];
1117b03ebc13SStefano Zampini       }
11186080607fSStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %D corners for edge %D (astart %D, estart %D)",found,i,e,idxs[0]);
1119b03ebc13SStefano Zampini     }
1120eee23b56SStefano Zampini 
1121eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1122b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1123b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1124b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1125b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1126b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1127b03ebc13SStefano Zampini     }
1128eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11294e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
11306080607fSStefano 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]);
11314e64d54eSstefano_zampini   }
11320569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11334e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11344e64d54eSstefano_zampini 
113576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1136a13144ffSStefano Zampini     /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1137a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1138a13144ffSStefano Zampini     ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1139a13144ffSStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1140a13144ffSStefano Zampini     for (i=0;i<nv;i++) {
1141a13144ffSStefano Zampini       PetscInt emax = 0,eemax = 0;
1142a13144ffSStefano Zampini 
1143a13144ffSStefano Zampini       if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1144580bdb30SBarry Smith       ierr = PetscArrayzero(emarks,nee+1);CHKERRQ(ierr);
1145a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1146a13144ffSStefano Zampini       for (j=1;j<nee+1;j++) {
1147a13144ffSStefano Zampini         if (emax < emarks[j]) {
1148a13144ffSStefano Zampini           emax = emarks[j];
1149a13144ffSStefano Zampini           eemax = j;
1150a13144ffSStefano Zampini         }
1151a13144ffSStefano Zampini       }
1152a13144ffSStefano Zampini       /* not relevant for edges */
1153a13144ffSStefano Zampini       if (!eemax) continue;
1154a13144ffSStefano Zampini 
1155a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
1156a13144ffSStefano Zampini         if (marks[jj[j]] && marks[jj[j]] != eemax) {
11576080607fSStefano Zampini           SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %D and %D) connected through the %D nodal dof at edge dof %D",marks[jj[j]]-1,eemax,i,jj[j]);
1158a13144ffSStefano Zampini         }
1159a13144ffSStefano Zampini       }
1160a13144ffSStefano Zampini     }
1161a13144ffSStefano Zampini     ierr = PetscFree(emarks);CHKERRQ(ierr);
1162a13144ffSStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
116376bd3646SJed Brown   }
1164a13144ffSStefano Zampini 
1165a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1166a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1167a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1168a13144ffSStefano Zampini   extmem *= maxsize;
1169a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1170a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1171a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1172a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1173a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1174213b8bfaSStefano Zampini 
1175a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1176a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1177a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1178a13144ffSStefano Zampini         mark = marks[jj[j]];
1179a13144ffSStefano Zampini 
1180a13144ffSStefano Zampini     /* not relevant */
1181a13144ffSStefano Zampini     if (!mark) continue;
1182a13144ffSStefano Zampini 
1183a13144ffSStefano Zampini     /* import extended row */
1184a13144ffSStefano Zampini     mark--;
1185a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1186a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
11876080607fSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %D > %D",extrowcum[mark] + size,extmem);
1188580bdb30SBarry Smith     ierr = PetscArraycpy(extrow+start,jj+ii[i],size);CHKERRQ(ierr);
1189a13144ffSStefano Zampini     extrowcum[mark] += size;
1190a13144ffSStefano Zampini   }
1191a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1192213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1193213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1194213b8bfaSStefano Zampini 
1195213b8bfaSStefano Zampini   /* Compress extrows */
1196a13144ffSStefano Zampini   cum  = 0;
1197a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1198a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1199a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1200a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1201a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1202a13144ffSStefano Zampini   }
1203a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1204a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1205a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1206a13144ffSStefano Zampini 
1207a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1208a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1209a13144ffSStefano Zampini 
1210a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1211a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1212c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1213c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1214a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1215a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1216a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12171e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1220213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1221a13144ffSStefano Zampini 
1222a13144ffSStefano Zampini   /* Defaults to identity */
1223c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1224a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1225a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1226a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1227a13144ffSStefano Zampini 
12281e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12291e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12301e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12311e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12321e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12331e0482f5SStefano Zampini     IS                     wis,gwis;
12341e0482f5SStefano Zampini     PetscInt               cnv,cne;
12351e0482f5SStefano Zampini 
12361e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12371e0482f5SStefano Zampini     if (fl2g) {
12381e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12391e0482f5SStefano Zampini     } else {
12401e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12411e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12421e0482f5SStefano Zampini     }
12431e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12441e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12451e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12461e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12471e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12481e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12491e0482f5SStefano Zampini 
12501e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12511e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12521e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12531e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12541e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12551e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12561e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12571e0482f5SStefano Zampini 
12581e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12591e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12601e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12611e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12621e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12631e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12641e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12651e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12661e0482f5SStefano Zampini   }
1267213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
12681e0482f5SStefano Zampini 
12691e0482f5SStefano Zampini #if defined(PRINT_GDET)
12701e0482f5SStefano Zampini   inc = 0;
12711e0482f5SStefano Zampini   lev = pcbddc->current_level;
12721e0482f5SStefano Zampini #endif
1273213b8bfaSStefano Zampini 
1274213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1275a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1276a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12771e0482f5SStefano Zampini     IS          cornersis = NULL;
12781e0482f5SStefano Zampini     PetscScalar cvals[2];
1279a13144ffSStefano Zampini 
12801e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12811e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12821e0482f5SStefano Zampini     }
12831e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1284a13144ffSStefano Zampini     if (Gins && GKins) {
12851683a169SBarry Smith       const PetscScalar *data;
1286a13144ffSStefano Zampini       const PetscInt    *rows,*cols;
1287a13144ffSStefano Zampini       PetscInt          nrh,nch,nrc,ncc;
1288a13144ffSStefano Zampini 
1289a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1290a13144ffSStefano Zampini       /* H1 */
1291a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1292a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
12931683a169SBarry Smith       ierr = MatDenseGetArrayRead(Gins,&data);CHKERRQ(ierr);
1294a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
12951683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(Gins,&data);CHKERRQ(ierr);
1296a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1297a13144ffSStefano Zampini       /* complement */
1298a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12996080607fSStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %D",i);
13006080607fSStefano 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);
13016080607fSStefano 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);
13021683a169SBarry Smith       ierr = MatDenseGetArrayRead(GKins,&data);CHKERRQ(ierr);
1303a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
13041683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(GKins,&data);CHKERRQ(ierr);
13051e0482f5SStefano Zampini 
13061e0482f5SStefano Zampini       /* coarse discrete gradient */
13071e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13081e0482f5SStefano Zampini         PetscInt cols[2];
13091e0482f5SStefano Zampini 
13101e0482f5SStefano Zampini         cols[0] = 2*i;
13111e0482f5SStefano Zampini         cols[1] = 2*i+1;
13121e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13131e0482f5SStefano Zampini       }
1314a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1315a13144ffSStefano Zampini     }
1316a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1317a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13181e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1319a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1320a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1321a13144ffSStefano Zampini   }
1322213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1323a13144ffSStefano Zampini 
1324a13144ffSStefano Zampini   /* Start assembling */
1325a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13261e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13271e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13281e0482f5SStefano Zampini   }
1329a13144ffSStefano Zampini 
1330a13144ffSStefano Zampini   /* Free */
1331c2151214SStefano Zampini   if (fl2g) {
1332c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1333c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1334c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1335c2151214SStefano Zampini     }
1336c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1337c2151214SStefano Zampini   }
1338eee23b56SStefano Zampini 
1339eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1340eee23b56SStefano Zampini   {
1341eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1342eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1343eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1344eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1345eee23b56SStefano Zampini 
1346eee23b56SStefano Zampini     /* find first primal edge */
1347eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1348eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1349eee23b56SStefano Zampini     } else {
1350eee23b56SStefano Zampini       if (fl2g) {
1351eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1352eee23b56SStefano Zampini       }
1353eee23b56SStefano Zampini       idxs = cedges;
1354eee23b56SStefano Zampini     }
1355eee23b56SStefano Zampini     cum = 0;
1356eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1357eee23b56SStefano Zampini 
1358eee23b56SStefano Zampini     /* adapt connected components */
1359eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1360eee23b56SStefano Zampini     graph->cptr[0] = 0;
1361eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1362eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1363eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1364eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1365eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1366eee23b56SStefano Zampini         ncc++;
1367eee23b56SStefano Zampini         lc--;
1368eee23b56SStefano Zampini         cum++;
1369eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1370eee23b56SStefano Zampini       }
1371eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1372eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1373eee23b56SStefano Zampini       ncc++;
1374eee23b56SStefano Zampini     }
1375eee23b56SStefano Zampini     graph->ncc = ncc;
1376eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1377eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1378eee23b56SStefano Zampini     }
1379eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1380eee23b56SStefano Zampini   }
1381213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1382c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1383c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1384213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1385eee23b56SStefano Zampini 
1386c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1387a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1388a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1389b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1390b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1391a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1392a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1393a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1394a13144ffSStefano Zampini 
1395a13144ffSStefano Zampini   /* Complete assembling */
1396a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13971e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13981e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13991e0482f5SStefano Zampini #if 0
14001e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14011e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14021e0482f5SStefano Zampini #endif
14031e0482f5SStefano Zampini   }
1404a13144ffSStefano Zampini 
1405a13144ffSStefano Zampini   /* set change of basis */
1406213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1407a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1408a13144ffSStefano Zampini 
1409a13144ffSStefano Zampini   PetscFunctionReturn(0);
1410a13144ffSStefano Zampini }
1411a13144ffSStefano Zampini 
1412d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1413d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1414d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1415d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1416d8203eabSStefano Zampini {
1417d8203eabSStefano Zampini   PetscErrorCode ierr;
1418d8203eabSStefano Zampini   PetscInt       i;
1419d8203eabSStefano Zampini 
1420d8203eabSStefano Zampini   PetscFunctionBegin;
1421d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1422d8203eabSStefano Zampini     PetscInt first,last;
1423d8203eabSStefano Zampini 
1424d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
142586fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1426d8203eabSStefano Zampini     if (i>=first && i < last) {
1427d8203eabSStefano Zampini       PetscScalar *data;
1428d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1429d8203eabSStefano Zampini       if (!has_const) {
1430d8203eabSStefano Zampini         data[i-first] = 1.;
1431d8203eabSStefano Zampini       } else {
143286fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
143386fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1434d8203eabSStefano Zampini       }
1435d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1436d8203eabSStefano Zampini     }
1437d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1438d8203eabSStefano Zampini   }
1439d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1440d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1441d8203eabSStefano Zampini     PetscInt first,last;
14428860a134SJunchao Zhang     ierr = VecLockReadPop(quad_vecs[i]);CHKERRQ(ierr);
1443d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1444d8203eabSStefano Zampini     if (i>=first && i < last) {
1445d8203eabSStefano Zampini       PetscScalar *data;
1446d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1447d8203eabSStefano Zampini       if (!has_const) {
1448d8203eabSStefano Zampini         data[i-first] = 0.;
1449d8203eabSStefano Zampini       } else {
145086fa73c5SStefano Zampini         data[2*i-first] = 0.;
145186fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1452d8203eabSStefano Zampini       }
1453d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1454d8203eabSStefano Zampini     }
1455d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
14568860a134SJunchao Zhang     ierr = VecLockReadPush(quad_vecs[i]);CHKERRQ(ierr);
1457d8203eabSStefano Zampini   }
1458d8203eabSStefano Zampini   PetscFunctionReturn(0);
1459d8203eabSStefano Zampini }
1460d8203eabSStefano Zampini 
14618ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1462669cc0f4SStefano Zampini {
1463a198735bSStefano Zampini   Mat                    loc_divudotp;
1464fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14658ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1466669cc0f4SStefano Zampini   PetscScalar            *vals;
1467669cc0f4SStefano Zampini   const PetscScalar      *array;
14680f04eeffSStefano Zampini   PetscInt               i,maxneighs = 0,maxsize,*gidxs;
1469a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14701ae86dd6SStefano Zampini   PetscMPIInt            rank;
1471a198735bSStefano Zampini   PetscErrorCode         ierr;
1472669cc0f4SStefano Zampini 
1473669cc0f4SStefano Zampini   PetscFunctionBegin;
1474a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14750f04eeffSStefano Zampini   for (i=0;i<n_neigh;i++) maxneighs = PetscMax(graph->count[shared[i][0]]+1,maxneighs);
1476820f2d46SBarry Smith   ierr = MPIU_Allreduce(MPI_IN_PLACE,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
14778037d520SStefano Zampini   if (!maxneighs) {
14788037d520SStefano Zampini     ierr  = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
14798037d520SStefano Zampini     *nnsp = NULL;
14808037d520SStefano Zampini     PetscFunctionReturn(0);
1481669cc0f4SStefano Zampini   }
1482669cc0f4SStefano Zampini   maxsize = 0;
1483a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
14840f27d399SStefano Zampini   ierr = PetscMalloc2(maxsize,&gidxs,maxsize,&vals);CHKERRQ(ierr);
1485669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1486669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14878ae0ca82SStefano Zampini   if (!transpose) {
14888ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14898ae0ca82SStefano Zampini   } else {
14908ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14918ae0ca82SStefano Zampini   }
1492669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14931ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1494d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1495669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
14968860a134SJunchao Zhang     ierr = VecLockReadPop(quad_vecs[i]);CHKERRQ(ierr);
1497669cc0f4SStefano Zampini   }
1498d8203eabSStefano Zampini 
1499669cc0f4SStefano Zampini   /* compute local quad vec */
1500a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15018ae0ca82SStefano Zampini   if (!transpose) {
1502a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15038ae0ca82SStefano Zampini   } else {
15048ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15058ae0ca82SStefano Zampini   }
1506669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15078ae0ca82SStefano Zampini   if (!transpose) {
1508a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15098ae0ca82SStefano Zampini   } else {
15108ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15118ae0ca82SStefano Zampini   }
1512fa23a32eSStefano Zampini   if (vl2l) {
1513187c917aSStefano Zampini     Mat        lA;
1514187c917aSStefano Zampini     VecScatter sc;
1515187c917aSStefano Zampini 
1516187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1517187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
15189448b7f1SJunchao Zhang     ierr = VecScatterCreate(v,NULL,vins,vl2l,&sc);CHKERRQ(ierr);
1519187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1520187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1521187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1522fa23a32eSStefano Zampini   } else {
1523fa23a32eSStefano Zampini     vins = v;
1524fa23a32eSStefano Zampini   }
1525fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1526669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15279a962809SStefano Zampini 
15281ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
1529ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRMPI(ierr);
15300f04eeffSStefano Zampini   for (i=1;i<n_neigh;i++) {
1531669cc0f4SStefano Zampini     const PetscInt    *idxs;
1532669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1533669cc0f4SStefano Zampini 
1534a040e873SStefano Zampini     idxs = shared[i];
1535a040e873SStefano Zampini     nn   = n_shared[i];
1536669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15371ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1538669cc0f4SStefano Zampini     idx  = -(idx+1);
15390f04eeffSStefano Zampini     if (idx < 0 || idx >= maxneighs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %D not in [0,%D)",idx,maxneighs);
15400f27d399SStefano Zampini     ierr = ISLocalToGlobalMappingApply(map,nn,idxs,gidxs);CHKERRQ(ierr);
15410f27d399SStefano Zampini     ierr = VecSetValues(quad_vecs[idx],nn,gidxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1542669cc0f4SStefano Zampini   }
1543a040e873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1544fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1545fa23a32eSStefano Zampini   if (vl2l) {
1546187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1547fa23a32eSStefano Zampini   }
1548669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
15490f27d399SStefano Zampini   ierr = PetscFree2(gidxs,vals);CHKERRQ(ierr);
1550669cc0f4SStefano Zampini 
1551669cc0f4SStefano Zampini   /* assemble near null space */
1552669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1553669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1554669cc0f4SStefano Zampini   }
1555669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1556669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
15573272d46bSStefano Zampini     ierr = VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view");CHKERRQ(ierr);
15588860a134SJunchao Zhang     ierr = VecLockReadPush(quad_vecs[i]);CHKERRQ(ierr);
1559669cc0f4SStefano Zampini   }
1560669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1561669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1562669cc0f4SStefano Zampini }
1563669cc0f4SStefano Zampini 
15647620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15657620a527SStefano Zampini {
15667620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15677620a527SStefano Zampini   PetscErrorCode ierr;
15687620a527SStefano Zampini 
15697620a527SStefano Zampini   PetscFunctionBegin;
15707620a527SStefano Zampini   if (primalv) {
15717620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15727620a527SStefano Zampini       IS list[2], newp;
15737620a527SStefano Zampini 
15747620a527SStefano Zampini       list[0] = primalv;
15757620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15767620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
15777620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
15787620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
15797620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15807620a527SStefano Zampini     } else {
15817620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
15827620a527SStefano Zampini     }
15837620a527SStefano Zampini   }
15847620a527SStefano Zampini   PetscFunctionReturn(0);
15857620a527SStefano Zampini }
1586669cc0f4SStefano Zampini 
15871c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15881c7a958bSStefano Zampini {
15891c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15901c7a958bSStefano Zampini 
15911c7a958bSStefano Zampini   PetscFunctionBegin;
15921c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15931c7a958bSStefano Zampini   PetscFunctionReturn(0);
15941c7a958bSStefano Zampini }
1595674ae819SStefano Zampini 
15961f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15971f4df5f7SStefano Zampini {
15981f4df5f7SStefano Zampini   PetscErrorCode ierr;
15991f4df5f7SStefano Zampini   Vec            local,global;
16001f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16011f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
16025c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
16031f4df5f7SStefano Zampini 
16041f4df5f7SStefano Zampini   PetscFunctionBegin;
16055c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
16065c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16075c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16081f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
160921ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16101f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
1611b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(global,PETSC_TRUE);CHKERRQ(ierr);
1612b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(local,PETSC_TRUE);CHKERRQ(ierr);
16136a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16146a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16156a8fc67bSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->vertex_size);CHKERRQ(ierr);
16166a8fc67bSStefano Zampini     }
16176a8fc67bSStefano Zampini     goto boundary;
16186a8fc67bSStefano Zampini   }
16195c5e10d6SStefano Zampini 
16201f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16211f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16221f4df5f7SStefano Zampini       PetscInt i;
16230c85b387SStefano Zampini 
16241f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16251f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16260c85b387SStefano Zampini         PetscInt bs;
16270c85b387SStefano Zampini 
16281f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16290c85b387SStefano Zampini         ierr = ISGetBlockSize(pcbddc->ISForDofs[i],&bs);CHKERRQ(ierr);
16300c85b387SStefano Zampini         ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
16311f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16321f4df5f7SStefano Zampini       }
16331f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16341f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16351f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16361f4df5f7SStefano Zampini     }
16371f4df5f7SStefano Zampini   } else {
163821ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
163921ef3d20SStefano Zampini       DM dm;
164021ef3d20SStefano Zampini 
164121ef3d20SStefano Zampini       ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
16424f819b78SStefano Zampini       if (!dm) {
16434f819b78SStefano Zampini         ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
164421ef3d20SStefano Zampini       }
164521ef3d20SStefano Zampini       if (dm) {
164621ef3d20SStefano Zampini         IS      *fields;
164721ef3d20SStefano Zampini         PetscInt nf,i;
16480c85b387SStefano Zampini 
164921ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
165021ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
165121ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16520c85b387SStefano Zampini           PetscInt bs;
16530c85b387SStefano Zampini 
165421ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16550c85b387SStefano Zampini           ierr = ISGetBlockSize(fields[i],&bs);CHKERRQ(ierr);
16560c85b387SStefano Zampini           ierr = ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs);CHKERRQ(ierr);
165721ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
165821ef3d20SStefano Zampini         }
165921ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
166021ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
166121ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
166221ef3d20SStefano Zampini         PetscContainer   c;
166321ef3d20SStefano Zampini 
166421ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
166521ef3d20SStefano Zampini         if (c) {
166621ef3d20SStefano Zampini           MatISLocalFields lf;
166721ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
166821ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
166921ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16701f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1671986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
167221ef3d20SStefano Zampini           if (i > 1) {
1673986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16741f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16751f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16761f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16771f4df5f7SStefano Zampini             }
16781f4df5f7SStefano Zampini           }
167921ef3d20SStefano Zampini         }
168021ef3d20SStefano Zampini       }
16817a0e7b2cSstefano_zampini     } else {
16827a0e7b2cSstefano_zampini       PetscInt i;
16837a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16847a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16857a0e7b2cSstefano_zampini       }
16861f4df5f7SStefano Zampini     }
1687986cdee1SStefano Zampini   }
16881f4df5f7SStefano Zampini 
16895c5e10d6SStefano Zampini boundary:
16901f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16911f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16927a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16937a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16941f4df5f7SStefano Zampini   }
16951f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16961f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16977a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16987a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16991f4df5f7SStefano Zampini   }
17001f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
17011f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
17021f4df5f7SStefano Zampini   }
17031f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
17041f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
17057620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
17067620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
17077620a527SStefano Zampini     IS        primalv = NULL;
17087620a527SStefano Zampini     PetscInt  i;
17098361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
17107a0e7b2cSstefano_zampini 
17117620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17127620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17137620a527SStefano Zampini     }
17147620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17158361f951SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17167620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17177620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17187620a527SStefano Zampini   }
17197620a527SStefano Zampini   /* early stage corner detection */
17207620a527SStefano Zampini   {
17217620a527SStefano Zampini     DM dm;
17227620a527SStefano Zampini 
17237620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17244f819b78SStefano Zampini     if (!dm) {
17254f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
17264f819b78SStefano Zampini     }
17277620a527SStefano Zampini     if (dm) {
17287620a527SStefano Zampini       PetscBool isda;
17297620a527SStefano Zampini 
17307620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17317620a527SStefano Zampini       if (isda) {
17327620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17337620a527SStefano Zampini         IS                     corners;
17347620a527SStefano Zampini         Mat                    lA;
17354f819b78SStefano Zampini         PetscBool              gl,lo;
17367620a527SStefano Zampini 
17374f819b78SStefano Zampini         {
17384f819b78SStefano Zampini           Vec               cvec;
17394f819b78SStefano Zampini           const PetscScalar *coords;
17404f819b78SStefano Zampini           PetscInt          dof,n,cdim;
17414f819b78SStefano Zampini           PetscBool         memc = PETSC_TRUE;
17424f819b78SStefano Zampini 
17434f819b78SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17444f819b78SStefano Zampini           ierr = DMGetCoordinates(dm,&cvec);CHKERRQ(ierr);
17454f819b78SStefano Zampini           ierr = VecGetLocalSize(cvec,&n);CHKERRQ(ierr);
17464f819b78SStefano Zampini           ierr = VecGetBlockSize(cvec,&cdim);CHKERRQ(ierr);
17474f819b78SStefano Zampini           n   /= cdim;
17484f819b78SStefano Zampini           ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
17494f819b78SStefano Zampini           ierr = PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords);CHKERRQ(ierr);
17504f819b78SStefano Zampini           ierr = VecGetArrayRead(cvec,&coords);CHKERRQ(ierr);
17514f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17524f819b78SStefano Zampini           memc = PETSC_FALSE;
17534f819b78SStefano Zampini #endif
17544f819b78SStefano Zampini           if (dof != 1) memc = PETSC_FALSE;
17554f819b78SStefano Zampini           if (memc) {
1756580bdb30SBarry Smith             ierr = PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof);CHKERRQ(ierr);
17574f819b78SStefano Zampini           } else { /* BDDC graph does not use any blocked information, we need to replicate the data */
17584f819b78SStefano Zampini             PetscReal *bcoords = pcbddc->mat_graph->coords;
17594f819b78SStefano Zampini             PetscInt  i, b, d;
17604f819b78SStefano Zampini 
17614f819b78SStefano Zampini             for (i=0;i<n;i++) {
17624f819b78SStefano Zampini               for (b=0;b<dof;b++) {
17634f819b78SStefano Zampini                 for (d=0;d<cdim;d++) {
17644f819b78SStefano Zampini                   bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]);
17654f819b78SStefano Zampini                 }
17664f819b78SStefano Zampini               }
17674f819b78SStefano Zampini             }
17684f819b78SStefano Zampini           }
17694f819b78SStefano Zampini           ierr = VecRestoreArrayRead(cvec,&coords);CHKERRQ(ierr);
17704f819b78SStefano Zampini           pcbddc->mat_graph->cdim  = cdim;
17714f819b78SStefano Zampini           pcbddc->mat_graph->cnloc = dof*n;
17724f819b78SStefano Zampini           pcbddc->mat_graph->cloc  = PETSC_FALSE;
17734f819b78SStefano Zampini         }
1774d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17757620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17767620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17777620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17784f819b78SStefano Zampini         lo   = (PetscBool)(l2l && corners);
1779820f2d46SBarry Smith         ierr = MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
17804f819b78SStefano Zampini         if (gl) { /* From PETSc's DMDA */
17817620a527SStefano Zampini           const PetscInt    *idx;
178272ed36d8SStefano Zampini           PetscInt          dof,bs,*idxout,n;
17837620a527SStefano Zampini 
178472ed36d8SStefano Zampini           ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
17857620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17867620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17877620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
178872ed36d8SStefano Zampini           if (bs == dof) {
17897620a527SStefano Zampini             ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17907620a527SStefano Zampini             ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
179172ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
179272ed36d8SStefano Zampini             PetscInt i,d;
179372ed36d8SStefano Zampini 
179472ed36d8SStefano Zampini             ierr = PetscMalloc1(dof*n,&idxout);CHKERRQ(ierr);
179572ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
179672ed36d8SStefano Zampini             ierr = ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout);CHKERRQ(ierr);
179772ed36d8SStefano Zampini 
179872ed36d8SStefano Zampini             bs = 1;
179972ed36d8SStefano Zampini             n *= dof;
180072ed36d8SStefano Zampini           }
18017620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1802d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
18037620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
18047620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
18057620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
18061c7a958bSStefano Zampini           pcbddc->corner_selected  = PETSC_TRUE;
18074f819b78SStefano Zampini           pcbddc->corner_selection = PETSC_TRUE;
18084f819b78SStefano Zampini         }
18094f819b78SStefano Zampini         if (corners) {
1810d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
18117620a527SStefano Zampini         }
18127620a527SStefano Zampini       }
18137620a527SStefano Zampini     }
18147620a527SStefano Zampini   }
18151c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
18161c7a958bSStefano Zampini     DM dm;
18171c7a958bSStefano Zampini 
18181c7a958bSStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
18194f819b78SStefano Zampini     if (!dm) {
18204f819b78SStefano Zampini       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
18211c7a958bSStefano Zampini     }
18224f819b78SStefano Zampini     if (dm) { /* this can get very expensive, I need to find a faster alternative */
18231c7a958bSStefano Zampini       Vec            vcoords;
18241c7a958bSStefano Zampini       PetscSection   section;
18251c7a958bSStefano Zampini       PetscReal      *coords;
18261c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
18271c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
18281c7a958bSStefano Zampini 
18291c7a958bSStefano Zampini       ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
183092fd8e1eSJed Brown       ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
18311c7a958bSStefano Zampini       ierr = PetscSectionGetNumFields(section,&nf);CHKERRQ(ierr);
18321c7a958bSStefano Zampini       ierr = DMCreateGlobalVector(dm,&vcoords);CHKERRQ(ierr);
18331c7a958bSStefano Zampini       ierr = VecGetLocalSize(vcoords,&nl);CHKERRQ(ierr);
18341c7a958bSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&coords);CHKERRQ(ierr);
18351c7a958bSStefano Zampini       ierr = PetscMalloc2(nf,&funcs,nf,&ctxs);CHKERRQ(ierr);
18361c7a958bSStefano Zampini       ierr = PetscMalloc1(nf,&ctxs[0]);CHKERRQ(ierr);
18371c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
18381c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
18391c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
18401c7a958bSStefano Zampini         PetscInt          i;
18411c7a958bSStefano Zampini         const PetscScalar *v;
18421c7a958bSStefano Zampini 
18431c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
18441c7a958bSStefano Zampini         ierr = DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords);CHKERRQ(ierr);
18451c7a958bSStefano Zampini         ierr = VecGetArrayRead(vcoords,&v);CHKERRQ(ierr);
18461c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
18471c7a958bSStefano Zampini         ierr = VecRestoreArrayRead(vcoords,&v);CHKERRQ(ierr);
18481c7a958bSStefano Zampini       }
18491c7a958bSStefano Zampini       ierr = VecDestroy(&vcoords);CHKERRQ(ierr);
18501c7a958bSStefano Zampini       ierr = PCSetCoordinates(pc,cdim,nl,coords);CHKERRQ(ierr);
18511c7a958bSStefano Zampini       ierr = PetscFree(coords);CHKERRQ(ierr);
18521c7a958bSStefano Zampini       ierr = PetscFree(ctxs[0]);CHKERRQ(ierr);
18531c7a958bSStefano Zampini       ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr);
18541c7a958bSStefano Zampini     }
18551c7a958bSStefano Zampini   }
18567a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18577a0e7b2cSstefano_zampini }
18587a0e7b2cSstefano_zampini 
18597a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18607a0e7b2cSstefano_zampini {
18617a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18627a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
18637a0e7b2cSstefano_zampini   IS              nis;
18647a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18657a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18667a0e7b2cSstefano_zampini 
18677a0e7b2cSstefano_zampini   PetscFunctionBegin;
18687a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18697a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18707a0e7b2cSstefano_zampini     /* init rootdata with true */
18711bd50df1SStefano Zampini     for (i=0;i<pc->pmat->rmap->n;i++) matis->sf_rootdata[i] = 1;
18727a0e7b2cSstefano_zampini   } else {
1873580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n);CHKERRQ(ierr);
18747a0e7b2cSstefano_zampini   }
1875580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,n);CHKERRQ(ierr);
18767a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18777a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18787a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18797a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18801bd50df1SStefano Zampini       matis->sf_leafdata[idxs[i]] = 1;
18817a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18821bd50df1SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18831bd50df1SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18841bd50df1SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
18851bd50df1SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
18867a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18877a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18887a0e7b2cSstefano_zampini   } else {
18897a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18907a0e7b2cSstefano_zampini   }
18917a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18921bd50df1SStefano Zampini     if (matis->sf_leafdata[i])
18937a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18947a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18957a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18967a0e7b2cSstefano_zampini   *is  = nis;
18971f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18981f4df5f7SStefano Zampini }
18991f4df5f7SStefano Zampini 
19003e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
19013e589ea0SStefano Zampini {
19023e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
19033e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
19043e589ea0SStefano Zampini   PetscErrorCode    ierr;
19053e589ea0SStefano Zampini 
19063e589ea0SStefano Zampini   PetscFunctionBegin;
19073e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
19083e589ea0SStefano Zampini     PetscFunctionReturn(0);
19093e589ea0SStefano Zampini   }
19103e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19113e589ea0SStefano Zampini     Vec swap;
19123e589ea0SStefano Zampini 
19133e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19143e589ea0SStefano Zampini     swap = pcbddc->work_change;
19153e589ea0SStefano Zampini     pcbddc->work_change = r;
19163e589ea0SStefano Zampini     r = swap;
19173e589ea0SStefano Zampini   }
19183e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19193e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192055c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
19213e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
192255c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1923c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19243e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
19253e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19263e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19273e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1928f913dca9SStefano Zampini     pcbddc->work_change = r;
19293e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19303e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19313e589ea0SStefano Zampini   }
19323e589ea0SStefano Zampini   PetscFunctionReturn(0);
19333e589ea0SStefano Zampini }
19343e589ea0SStefano Zampini 
1935a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1936a3df083aSStefano Zampini {
1937a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1938a3df083aSStefano Zampini   PetscErrorCode          ierr;
1939a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1940a3df083aSStefano Zampini 
1941a3df083aSStefano Zampini   PetscFunctionBegin;
1942a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1943a3df083aSStefano Zampini   if (transpose) {
1944a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1945a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1946a3df083aSStefano Zampini   } else {
1947a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1948a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1949a3df083aSStefano Zampini   }
1950a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1951a3df083aSStefano Zampini   if (apply_right) {
1952a3df083aSStefano Zampini     const PetscScalar *ax;
1953a3df083aSStefano Zampini     PetscInt          nl,i;
1954a3df083aSStefano Zampini 
1955a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1956a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1957580bdb30SBarry Smith     ierr = PetscArraycpy(ctx->work,ax,nl);CHKERRQ(ierr);
1958a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1959a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1960a3df083aSStefano Zampini       PetscScalar    sum,val;
1961a3df083aSStefano Zampini       const PetscInt *idxs;
1962a3df083aSStefano Zampini       PetscInt       nz,j;
1963a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1964a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1965a3df083aSStefano Zampini       sum = 0.;
1966a3df083aSStefano Zampini       if (ctx->apply_p0) {
1967a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1968a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1969a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1970a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1971a3df083aSStefano Zampini         }
1972a3df083aSStefano Zampini       } else {
1973a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1974a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1975a3df083aSStefano Zampini         }
1976a3df083aSStefano Zampini       }
1977a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1978a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1979a3df083aSStefano Zampini     }
1980a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1981a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1982a3df083aSStefano Zampini   }
1983a3df083aSStefano Zampini   if (transpose) {
1984a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1985a3df083aSStefano Zampini   } else {
1986a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1987a3df083aSStefano Zampini   }
1988a3df083aSStefano Zampini   if (reset_x) {
1989a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1990a3df083aSStefano Zampini   }
1991a3df083aSStefano Zampini   if (apply_left) {
1992a3df083aSStefano Zampini     PetscScalar *ay;
1993a3df083aSStefano Zampini     PetscInt    i;
1994a3df083aSStefano Zampini 
1995a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1996a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1997a3df083aSStefano Zampini       PetscScalar    sum,val;
1998a3df083aSStefano Zampini       const PetscInt *idxs;
1999a3df083aSStefano Zampini       PetscInt       nz,j;
2000a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2001a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
2002a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
2003a3df083aSStefano Zampini       if (ctx->apply_p0) {
2004a3df083aSStefano Zampini         sum = 0.;
2005a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2006a3df083aSStefano Zampini           sum += ay[idxs[j]];
2007a3df083aSStefano Zampini           ay[idxs[j]] += val;
2008a3df083aSStefano Zampini         }
2009a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
2010a3df083aSStefano Zampini       } else {
2011a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2012a3df083aSStefano Zampini           ay[idxs[j]] += val;
2013a3df083aSStefano Zampini         }
2014a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
2015a3df083aSStefano Zampini       }
2016a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
2017a3df083aSStefano Zampini     }
2018a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
2019a3df083aSStefano Zampini   }
2020a3df083aSStefano Zampini   PetscFunctionReturn(0);
2021a3df083aSStefano Zampini }
2022a3df083aSStefano Zampini 
2023a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
2024a3df083aSStefano Zampini {
2025a3df083aSStefano Zampini   PetscErrorCode ierr;
2026a3df083aSStefano Zampini 
2027a3df083aSStefano Zampini   PetscFunctionBegin;
2028a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
2029a3df083aSStefano Zampini   PetscFunctionReturn(0);
2030a3df083aSStefano Zampini }
2031a3df083aSStefano Zampini 
2032a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
2033a3df083aSStefano Zampini {
2034a3df083aSStefano Zampini   PetscErrorCode ierr;
2035a3df083aSStefano Zampini 
2036a3df083aSStefano Zampini   PetscFunctionBegin;
2037a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
2038a3df083aSStefano Zampini   PetscFunctionReturn(0);
2039a3df083aSStefano Zampini }
2040a3df083aSStefano Zampini 
2041a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
2042a3df083aSStefano Zampini {
2043a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
2044a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
2045a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
2046a3df083aSStefano Zampini   PetscErrorCode          ierr;
2047a3df083aSStefano Zampini 
2048a3df083aSStefano Zampini   PetscFunctionBegin;
2049a3df083aSStefano Zampini   if (!restore) {
20501dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2051a3df083aSStefano Zampini     PetscScalar        *work;
2052b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2053a3df083aSStefano Zampini 
20549a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20559a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
2056a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
2057a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
2058a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2059a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
2060a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
2061a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
2062a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2063a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2064a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2065a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2066a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2067a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2068059032f7SStefano Zampini     if (reuse) {
2069a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20701dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2071059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2072059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2073059032f7SStefano Zampini       PetscInt               i;
2074059032f7SStefano Zampini 
2075059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2076059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2077059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2078059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2079059032f7SStefano Zampini       }
2080059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20811dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2082059032f7SStefano Zampini     }
2083a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2084a3df083aSStefano Zampini     ctx->work = work;
2085a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2086a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2087a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2088a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2089a3df083aSStefano Zampini 
2090a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2091a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2092a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2093a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2094a3df083aSStefano Zampini   } else {
20951dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20961dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20971dd7afcfSStefano Zampini     }
2098a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2099a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2100a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
21011dd7afcfSStefano Zampini     ctx->A = NULL;
21021dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
21031dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
21041dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
21051dd7afcfSStefano Zampini     if (ctx->free) {
2106059032f7SStefano Zampini       PetscInt i;
21071dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2108059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2109059032f7SStefano Zampini       }
2110059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2111059032f7SStefano Zampini     }
2112a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2113a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2114a3df083aSStefano Zampini   }
2115a3df083aSStefano Zampini   PetscFunctionReturn(0);
2116a3df083aSStefano Zampini }
2117a3df083aSStefano Zampini 
2118a3df083aSStefano Zampini /* used just in bddc debug mode */
2119a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2120a3df083aSStefano Zampini {
2121a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2122a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2123a3df083aSStefano Zampini   Mat            An;
2124a3df083aSStefano Zampini   PetscErrorCode ierr;
2125a3df083aSStefano Zampini 
2126a3df083aSStefano Zampini   PetscFunctionBegin;
2127a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2128a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2129a3df083aSStefano Zampini   if (is1) {
21307dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2131a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2132a3df083aSStefano Zampini   } else {
2133a3df083aSStefano Zampini     *B = An;
2134a3df083aSStefano Zampini   }
2135a3df083aSStefano Zampini   PetscFunctionReturn(0);
2136a3df083aSStefano Zampini }
2137a3df083aSStefano Zampini 
21381cf9b237SStefano Zampini /* TODO: add reuse flag */
21391cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
21401cf9b237SStefano Zampini {
21411cf9b237SStefano Zampini   Mat            Bt;
21421cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
21431cf9b237SStefano Zampini   const PetscInt *ii,*ij;
21441cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
21451cf9b237SStefano Zampini   PetscBool      flg_row;
21461cf9b237SStefano Zampini   PetscErrorCode ierr;
21471cf9b237SStefano Zampini 
21481cf9b237SStefano Zampini   PetscFunctionBegin;
21491cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
21501cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21511cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
21521cf9b237SStefano Zampini   nnz = n;
21531cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21541cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21551cf9b237SStefano Zampini   }
21561cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
21571cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
21581cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
21591cf9b237SStefano Zampini   nnz = 0;
21601cf9b237SStefano Zampini   bii[0] = 0;
21611cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21621cf9b237SStefano Zampini     PetscInt j;
21631cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21641cf9b237SStefano Zampini       PetscScalar entry = a[j];
21653272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21661cf9b237SStefano Zampini         bij[nnz] = ij[j];
21671cf9b237SStefano Zampini         bdata[nnz] = entry;
21681cf9b237SStefano Zampini         nnz++;
21691cf9b237SStefano Zampini       }
21701cf9b237SStefano Zampini     }
21711cf9b237SStefano Zampini     bii[i+1] = nnz;
21721cf9b237SStefano Zampini   }
21731cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21741cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21751cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21761cf9b237SStefano Zampini   {
21771cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21781cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21791cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21801cf9b237SStefano Zampini   }
21813272d46bSStefano Zampini   if (*B == A) {
21823272d46bSStefano Zampini     ierr = MatDestroy(&A);CHKERRQ(ierr);
21833272d46bSStefano Zampini   }
21841cf9b237SStefano Zampini   *B = Bt;
21851cf9b237SStefano Zampini   PetscFunctionReturn(0);
21861cf9b237SStefano Zampini }
21871cf9b237SStefano Zampini 
21888361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21894f1b2e48SStefano Zampini {
2190c80a6c00SStefano Zampini   Mat                    B = NULL;
2191c80a6c00SStefano Zampini   DM                     dm;
21924f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21934f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21944f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2195c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21964f1b2e48SStefano Zampini   PetscInt               i,n;
21974f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2198c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21994f1b2e48SStefano Zampini   PetscErrorCode         ierr;
22004f1b2e48SStefano Zampini 
22014f1b2e48SStefano Zampini   PetscFunctionBegin;
2202a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2203a2eca866SStefano Zampini   if (cc) *cc = NULL;
2204a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2205c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2206c80a6c00SStefano Zampini   ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
22074f819b78SStefano Zampini   if (!dm) {
22084f819b78SStefano Zampini     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2209c80a6c00SStefano Zampini   }
2210c80a6c00SStefano Zampini   if (dm) {
2211c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2212c80a6c00SStefano Zampini   }
22138361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
22148361f951SStefano Zampini 
2215c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2216c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2217c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2218c80a6c00SStefano Zampini     IS             cellNumbering;
2219c80a6c00SStefano Zampini     const PetscInt *cellNum;
2220c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2221c80a6c00SStefano Zampini     PetscSection   section;
2222c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2223c80a6c00SStefano Zampini     PetscSF        sfPoint;
2224c80a6c00SStefano Zampini     PetscErrorCode ierr;
2225c80a6c00SStefano Zampini 
2226c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2227c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2228c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2229c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2230c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2231c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2232c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2233c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2234b0441da4SMatthew G. Knepley     ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr);
2235b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
2236956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2237c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2238c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2239c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2240c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2241c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2242c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2243c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2244c80a6c00SStefano Zampini         const PetscInt point = adj[a];
22455cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2246c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2247c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2248c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2249c80a6c00SStefano Zampini           *pBuf = point;
2250c80a6c00SStefano Zampini         }
2251c80a6c00SStefano Zampini       }
2252c80a6c00SStefano Zampini       n++;
2253c80a6c00SStefano Zampini     }
2254b0441da4SMatthew G. Knepley     ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr);
2255c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2256c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2257c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2258c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2259c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2260c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2261c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2262c80a6c00SStefano Zampini     }
2263c80a6c00SStefano Zampini     xadj[n] = size;
2264c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2265c80a6c00SStefano Zampini     /* Clean up */
2266c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2267c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2268c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2269c80a6c00SStefano Zampini     graph->xadj = xadj;
2270c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2271c80a6c00SStefano Zampini   } else {
2272c80a6c00SStefano Zampini     Mat       A;
22738361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2274c80a6c00SStefano Zampini 
2275c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
227663c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2277a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
227863c961adSStefano Zampini       PetscFunctionReturn(0);
227963c961adSStefano Zampini     }
22807ebab0bbSStefano Zampini     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22814f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22821cf9b237SStefano Zampini       PetscBool isseqdense;
22831cf9b237SStefano Zampini 
22841cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22851cf9b237SStefano Zampini       if (!isseqdense) {
22864f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22871cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22881cf9b237SStefano Zampini         PetscScalar *array;
22891cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22901cf9b237SStefano Zampini 
22911cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22921cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22931cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22941cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22951cf9b237SStefano Zampini           PetscInt j;
22961cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22971cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22981cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22991cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
23001cf9b237SStefano Zampini           }
23011cf9b237SStefano Zampini         }
23021cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
23039d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
23041cf9b237SStefano Zampini       }
23054f1b2e48SStefano Zampini     } else {
2306c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
23074f1b2e48SStefano Zampini       B = A;
23084f1b2e48SStefano Zampini     }
23094f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23104f1b2e48SStefano Zampini 
23114f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
23124f1b2e48SStefano Zampini     if (filter) {
23134f1b2e48SStefano Zampini       PetscScalar *data;
23144f1b2e48SStefano Zampini       PetscInt    j,cum;
23154f1b2e48SStefano Zampini 
23164f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
23174f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
23184f1b2e48SStefano Zampini       cum = 0;
23194f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
23204f1b2e48SStefano Zampini         PetscInt t;
23214f1b2e48SStefano Zampini 
23224f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
23234f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
23244f1b2e48SStefano Zampini             continue;
23254f1b2e48SStefano Zampini           }
23264f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
23274f1b2e48SStefano Zampini         }
23284f1b2e48SStefano Zampini         t = xadj_filtered[i];
23294f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
23304f1b2e48SStefano Zampini         cum += t;
23314f1b2e48SStefano Zampini       }
23324f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
23334f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
23344f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
23354f1b2e48SStefano Zampini     } else {
23364f1b2e48SStefano Zampini       graph->xadj = xadj;
23374f1b2e48SStefano Zampini       graph->adjncy = adjncy;
23384f1b2e48SStefano Zampini     }
2339c80a6c00SStefano Zampini   }
2340c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2341c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2342c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2343c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2344c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2345c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
23464f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
23474f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2348c80a6c00SStefano Zampini 
23494f1b2e48SStefano Zampini   /* partial clean up */
23504f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2351c80a6c00SStefano Zampini   if (B) {
2352c80a6c00SStefano Zampini     PetscBool flg_row;
23534f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23544f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
23554f1b2e48SStefano Zampini   }
2356c80a6c00SStefano Zampini   if (isplex) {
2357c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2358c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2359c80a6c00SStefano Zampini   }
23604f1b2e48SStefano Zampini 
23614f1b2e48SStefano Zampini   /* get back data */
2362c80a6c00SStefano Zampini   if (isplex) {
2363c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2364c80a6c00SStefano Zampini     if (cc || primalv) {
2365c80a6c00SStefano Zampini       Mat          A;
2366c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2367c80a6c00SStefano Zampini       PetscSection subSection;
2368c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2369c80a6c00SStefano Zampini 
2370c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2371c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2372c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2373c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2374c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2375c80a6c00SStefano Zampini 
2376c80a6c00SStefano Zampini       cids[0] = 0;
2377c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2378c80a6c00SStefano Zampini         PetscInt j;
2379c80a6c00SStefano Zampini 
2380c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2381c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2382c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2383c80a6c00SStefano Zampini 
2384c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2385c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
238620c3699dSStefano Zampini             PetscInt s, pp, p = closure[k], off, dof, cdof;
2387c80a6c00SStefano Zampini 
2388c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection,p,&cdof);CHKERRQ(ierr);
2389c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2390c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2391c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2392c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2393c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2394c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2395c80a6c00SStefano Zampini               } else { /* cross-vertex */
2396c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2397c80a6c00SStefano Zampini               }
2398c80a6c00SStefano Zampini             }
239920c3699dSStefano Zampini             ierr = DMPlexGetTreeParent(dm,p,&pp,NULL);CHKERRQ(ierr);
240020c3699dSStefano Zampini             if (pp != p) {
240120c3699dSStefano Zampini               ierr = PetscSectionGetConstraintDof(subSection,pp,&cdof);CHKERRQ(ierr);
240220c3699dSStefano Zampini               ierr = PetscSectionGetOffset(subSection,pp,&off);CHKERRQ(ierr);
240320c3699dSStefano Zampini               ierr = PetscSectionGetDof(subSection,pp,&dof);CHKERRQ(ierr);
240420c3699dSStefano Zampini               for (s = 0; s < dof-cdof; s++) {
240520c3699dSStefano Zampini                 if (PetscBTLookupSet(btvt,off+s)) continue;
240620c3699dSStefano Zampini                 if (!PetscBTLookup(btv,off+s)) {
240720c3699dSStefano Zampini                   ids[cum++] = off+s;
240820c3699dSStefano Zampini                 } else { /* cross-vertex */
240920c3699dSStefano Zampini                   pids[cump++] = off+s;
241020c3699dSStefano Zampini                 }
241120c3699dSStefano Zampini               }
241220c3699dSStefano Zampini             }
2413c80a6c00SStefano Zampini           }
2414c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2415c80a6c00SStefano Zampini         }
2416c80a6c00SStefano Zampini         cids[i+1] = cum;
2417c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2418c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2419c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2420c80a6c00SStefano Zampini         }
2421c80a6c00SStefano Zampini       }
2422c80a6c00SStefano Zampini       if (cc) {
2423c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2424c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2425c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2426c80a6c00SStefano Zampini         }
2427c80a6c00SStefano Zampini         *cc = cc_n;
2428c80a6c00SStefano Zampini       }
2429c80a6c00SStefano Zampini       if (primalv) {
2430c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2431c80a6c00SStefano Zampini       }
2432c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2433c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2434c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2435c80a6c00SStefano Zampini     }
2436c80a6c00SStefano Zampini   } else {
24371cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
24381cf9b237SStefano Zampini     if (cc) {
24394f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
24404f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
24414f1b2e48SStefano 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);
24424f1b2e48SStefano Zampini       }
24434f1b2e48SStefano Zampini       *cc = cc_n;
24441cf9b237SStefano Zampini     }
2445c80a6c00SStefano Zampini   }
24464f1b2e48SStefano Zampini   /* clean up graph */
24470a545947SLisandro Dalcin   graph->xadj = NULL;
24480a545947SLisandro Dalcin   graph->adjncy = NULL;
24494f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
24504f1b2e48SStefano Zampini   PetscFunctionReturn(0);
24514f1b2e48SStefano Zampini }
24524f1b2e48SStefano Zampini 
24535408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
24545408967cSStefano Zampini {
24555408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24565408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2457dee84bffSStefano Zampini   IS             dirIS = NULL;
24584f1b2e48SStefano Zampini   PetscInt       i;
24595408967cSStefano Zampini   PetscErrorCode ierr;
24605408967cSStefano Zampini 
24615408967cSStefano Zampini   PetscFunctionBegin;
2462dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
24635408967cSStefano Zampini   if (zerodiag) {
24645408967cSStefano Zampini     Mat            A;
24655408967cSStefano Zampini     Vec            vec3_N;
24665408967cSStefano Zampini     PetscScalar    *vals;
24675408967cSStefano Zampini     const PetscInt *idxs;
2468d12d3064SStefano Zampini     PetscInt       nz,*count;
24695408967cSStefano Zampini 
24705408967cSStefano Zampini     /* p0 */
24715408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
24725408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24735408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24745408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24754f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24765408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24775408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24785408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24795408967cSStefano Zampini     /* v_I */
24805408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24815408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24825408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24835408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24845408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24855408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24865408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24875408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24885408967cSStefano Zampini     if (dirIS) {
24895408967cSStefano Zampini       PetscInt n;
24905408967cSStefano Zampini 
24915408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24925408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24935408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24945408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24955408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24965408967cSStefano Zampini     }
24975408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24985408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24995408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
25005408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2501669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
25025408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
25035408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
25049a962809SStefano 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]));
25055408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
25065408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2507d12d3064SStefano Zampini 
2508d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2509d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2510d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2511d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2512d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2513d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25146080607fSStefano 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]);
2515d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2516d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
25175408967cSStefano Zampini   }
2518dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
25195408967cSStefano Zampini 
25205408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
25215408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
25224f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
25235408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
25244f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
25255408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2526f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2527f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
25286080607fSStefano Zampini     if (val != -PetscGlobalRank-i) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %D instead of %g",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i);
2529f2a566d8SStefano Zampini   }
25305408967cSStefano Zampini   PetscFunctionReturn(0);
25315408967cSStefano Zampini }
25325408967cSStefano Zampini 
25333b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2534339f8db1SStefano Zampini {
2535339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
25363b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
25373b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
25384edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
25394edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2540339f8db1SStefano Zampini   PetscErrorCode ierr;
2541339f8db1SStefano Zampini 
2542339f8db1SStefano Zampini   PetscFunctionBegin;
25433b03f7bbSStefano Zampini   if (reuse) goto project_b0;
25449f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
25459f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2546a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2547a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2548a3df083aSStefano Zampini   }
2549a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
25503b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
25513b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
25523b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
25533b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
25544f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
25554f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
25561ae86dd6SStefano Zampini      since the local Schur complements are already SPD
25574f1b2e48SStefano Zampini   */
255840fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
25597fbe2174Sstefano_zampini     IS        iP = NULL;
25603b03f7bbSStefano Zampini     PetscInt  p,*pp;
25613b03f7bbSStefano Zampini     PetscBool flg;
25624f1b2e48SStefano Zampini 
25633b03f7bbSStefano Zampini     ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp);CHKERRQ(ierr);
25643b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
256528b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
25663b03f7bbSStefano Zampini     ierr = PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg);CHKERRQ(ierr);
256728b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
25683b03f7bbSStefano Zampini     if (!flg) {
25693b03f7bbSStefano Zampini       n = 1;
25703b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25713b03f7bbSStefano Zampini     }
25723b03f7bbSStefano Zampini 
25733b03f7bbSStefano Zampini     bsp = 0;
25743b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25753b03f7bbSStefano Zampini       PetscInt bs;
25763b03f7bbSStefano Zampini 
25773b03f7bbSStefano Zampini       if (pp[p] < 0 || pp[p] > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",pp[p]);
25783b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25793b03f7bbSStefano Zampini       bsp += bs;
25803b03f7bbSStefano Zampini     }
25813b03f7bbSStefano Zampini     ierr = PetscMalloc1(bsp,&bzerodiag);CHKERRQ(ierr);
25823b03f7bbSStefano Zampini     bsp  = 0;
25833b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25843b03f7bbSStefano Zampini       const PetscInt *idxs;
25853b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25863b03f7bbSStefano Zampini 
25873b03f7bbSStefano Zampini       ierr = ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs);CHKERRQ(ierr);
25883b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl);CHKERRQ(ierr);
25893b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
25903b03f7bbSStefano Zampini       ierr = PetscMalloc1(npl/bs,&bidxs);CHKERRQ(ierr);
25913b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25923b03f7bbSStefano Zampini         PetscInt i;
25933b03f7bbSStefano Zampini 
25943b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25953b03f7bbSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]);CHKERRQ(ierr);
25963b03f7bbSStefano Zampini         bsp++;
25973b03f7bbSStefano Zampini       }
25983b03f7bbSStefano Zampini       ierr = PetscFree(bidxs);CHKERRQ(ierr);
25993b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs);CHKERRQ(ierr);
26003b03f7bbSStefano Zampini     }
26013b03f7bbSStefano Zampini     ierr = ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures);CHKERRQ(ierr);
26023b03f7bbSStefano Zampini 
26037fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
26047fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
26057fbe2174Sstefano_zampini     if (iP) {
26067fbe2174Sstefano_zampini       IS newpressures;
26077fbe2174Sstefano_zampini 
26087fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
26097fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
26107fbe2174Sstefano_zampini       pressures = newpressures;
26117fbe2174Sstefano_zampini     }
261240fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
261340fa8d13SStefano Zampini     if (!sorted) {
261440fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
261540fa8d13SStefano Zampini     }
26163b03f7bbSStefano Zampini     ierr = PetscFree(pp);CHKERRQ(ierr);
261740fa8d13SStefano Zampini   }
26183b03f7bbSStefano Zampini 
261997d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
262097d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
262127b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
262297d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2623339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2624339f8db1SStefano Zampini   if (!sorted) {
2625339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2626339f8db1SStefano Zampini   }
26274edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26284edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2629339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
26304f1b2e48SStefano Zampini   if (!nz) {
26314f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
26324f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
263340fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
263440fa8d13SStefano Zampini   }
26354f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
26363b03f7bbSStefano Zampini 
26374f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
26384f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
26393b03f7bbSStefano Zampini   benign_n         = 0;
26401f4df5f7SStefano Zampini   n_interior_dofs  = 0;
26411f4df5f7SStefano Zampini   interior_dofs    = NULL;
26424edc6404Sstefano_zampini   nneu             = 0;
26434edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
26444edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
26454edc6404Sstefano_zampini   }
26463369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
26474edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
26481f4df5f7SStefano Zampini     PetscInt n,i,j;
26491f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
26501f4df5f7SStefano Zampini     PetscInt *iwork;
26511f4df5f7SStefano Zampini 
26521f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
26531f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26541f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
26551f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
265690648384SStefano Zampini     for (i=1;i<n_neigh;i++)
26571f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
26581f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
26591f4df5f7SStefano Zampini     for (i=0;i<n;i++)
26601f4df5f7SStefano Zampini       if (!iwork[i])
26611f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
26621f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
26631f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
26641f4df5f7SStefano Zampini   }
26654f1b2e48SStefano Zampini   if (has_null_pressures) {
26664f1b2e48SStefano Zampini     IS             *subs;
26674edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26681f4df5f7SStefano Zampini     const PetscInt *idxs;
26691f4df5f7SStefano Zampini     PetscScalar    *array;
26701f4df5f7SStefano Zampini     Vec            *work;
26711f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
26724f1b2e48SStefano Zampini 
26734f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26744f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26751f4df5f7SStefano 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) */
26764edc6404Sstefano_zampini     if (checkb) {
26771f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
26781f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
26791f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
26801f4df5f7SStefano Zampini       /* work[0] = 1_p */
26811f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
26821f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
26831f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26841f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
26851f4df5f7SStefano Zampini       /* work[0] = 1_v */
26861f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
26871f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
26881f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26891f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
26901f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
26911f4df5f7SStefano Zampini     }
26923b03f7bbSStefano Zampini 
26933b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26943b03f7bbSStefano Zampini       IS       *is;
26953b03f7bbSStefano Zampini       PetscInt b,totb;
26963b03f7bbSStefano Zampini 
26973b03f7bbSStefano Zampini       totb  = bsp;
26983b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26993b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
27003b03f7bbSStefano Zampini       ierr  = PetscCalloc1(nsubs*totb,&zerodiag_subs);CHKERRQ(ierr);
27013b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
27024f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
27034f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
27044f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
27054f1b2e48SStefano Zampini           PetscInt               nl;
27064f1b2e48SStefano Zampini 
27073b03f7bbSStefano Zampini           if (subs) {
27084f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
27093b03f7bbSStefano Zampini           } else {
27103b03f7bbSStefano Zampini             IS tis;
27113b03f7bbSStefano Zampini 
27123b03f7bbSStefano Zampini             ierr = MatGetLocalSize(pcbddc->local_mat,&nl,NULL);CHKERRQ(ierr);
27133b03f7bbSStefano Zampini             ierr = ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis);CHKERRQ(ierr);
27143b03f7bbSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(tis,&l2g);CHKERRQ(ierr);
27153b03f7bbSStefano Zampini             ierr = ISDestroy(&tis);CHKERRQ(ierr);
27163b03f7bbSStefano Zampini           }
27173b03f7bbSStefano Zampini           ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs);CHKERRQ(ierr);
27184f1b2e48SStefano Zampini           ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
27194f1b2e48SStefano Zampini           if (nl) {
27204f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
27214f1b2e48SStefano Zampini 
27224edc6404Sstefano_zampini             if (checkb) {
27231f4df5f7SStefano Zampini               ierr = VecSet(matis->x,0);CHKERRQ(ierr);
27241f4df5f7SStefano Zampini               ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
27251f4df5f7SStefano Zampini               ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
27261f4df5f7SStefano Zampini               ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27271f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
27281f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27291f4df5f7SStefano Zampini               ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
27301f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
27311f4df5f7SStefano Zampini               ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
27321f4df5f7SStefano Zampini               ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
27331f4df5f7SStefano Zampini               ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
27341f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
27351f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27361f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
27371f4df5f7SStefano Zampini                   break;
27381f4df5f7SStefano Zampini                 }
27391f4df5f7SStefano Zampini               }
27401f4df5f7SStefano Zampini               ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
27411f4df5f7SStefano Zampini             }
27426632bad2Sstefano_zampini             if (valid && nneu) {
27436632bad2Sstefano_zampini               const PetscInt *idxs;
27441f4df5f7SStefano Zampini               PetscInt       nzb;
27451f4df5f7SStefano Zampini 
27466632bad2Sstefano_zampini               ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27476632bad2Sstefano_zampini               ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
27486632bad2Sstefano_zampini               ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
27491f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
27501f4df5f7SStefano Zampini             }
27511f4df5f7SStefano Zampini             if (valid && pressures) {
27523b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
27533b03f7bbSStefano Zampini               PetscInt i1,i2;
27543b03f7bbSStefano Zampini 
27554f1b2e48SStefano Zampini               ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
27563b03f7bbSStefano Zampini               ierr = ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp);CHKERRQ(ierr);
27573b03f7bbSStefano Zampini               ierr = ISGetLocalSize(tmp,&i1);CHKERRQ(ierr);
27583b03f7bbSStefano Zampini               ierr = ISGetLocalSize(t_zerodiag_subs,&i2);CHKERRQ(ierr);
27593b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
27604f1b2e48SStefano Zampini               ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
27613b03f7bbSStefano Zampini               ierr = ISDestroy(&tmp);CHKERRQ(ierr);
27624f1b2e48SStefano Zampini             }
27634f1b2e48SStefano Zampini             if (valid) {
27643b03f7bbSStefano Zampini               ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]);CHKERRQ(ierr);
27653b03f7bbSStefano Zampini               benign_n++;
27663b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27674f1b2e48SStefano Zampini           }
27684f1b2e48SStefano Zampini           ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
27694f1b2e48SStefano Zampini           ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
27704f1b2e48SStefano Zampini         }
27713b03f7bbSStefano Zampini       }
27724f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27734f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27741f4df5f7SStefano Zampini 
27756632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27761f4df5f7SStefano Zampini       if (valid && pressures) {
27774f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
27784f1b2e48SStefano Zampini       }
27794edc6404Sstefano_zampini       if (valid && checkb) {
27801f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
27811f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
27821f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
27831f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27841f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27851f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27861f4df5f7SStefano Zampini             break;
27871f4df5f7SStefano Zampini           }
27881f4df5f7SStefano Zampini         }
27891f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
27901f4df5f7SStefano Zampini       }
27914f1b2e48SStefano Zampini       if (valid) {
27923b03f7bbSStefano Zampini         benign_n = 1;
27933b03f7bbSStefano Zampini         ierr = PetscMalloc1(benign_n,&zerodiag_subs);CHKERRQ(ierr);
27944f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
27954f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27964f1b2e48SStefano Zampini       }
27974f1b2e48SStefano Zampini     }
27984edc6404Sstefano_zampini     if (checkb) {
27991f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
28004f1b2e48SStefano Zampini     }
28011f4df5f7SStefano Zampini   }
28021f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
28034f1b2e48SStefano Zampini 
28043b03f7bbSStefano Zampini   if (!benign_n) {
2805b9b0e38cSStefano Zampini     PetscInt n;
2806b9b0e38cSStefano Zampini 
28074f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28084f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2809b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
281076a58201SStefano Zampini     if (n) have_null = PETSC_FALSE;
2811b9b0e38cSStefano Zampini   }
28124f1b2e48SStefano Zampini 
28134f1b2e48SStefano Zampini   /* final check for null pressures */
28144f1b2e48SStefano Zampini   if (zerodiag && pressures) {
28153b03f7bbSStefano Zampini     ierr = ISEqual(pressures,zerodiag,&have_null);CHKERRQ(ierr);
28164f1b2e48SStefano Zampini   }
28174f1b2e48SStefano Zampini 
28184f1b2e48SStefano Zampini   if (recompute_zerodiag) {
28194f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
28203b03f7bbSStefano Zampini     if (benign_n == 1) {
28214f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
28224f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
28234f1b2e48SStefano Zampini     } else {
28244f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
28254f1b2e48SStefano Zampini 
28264f1b2e48SStefano Zampini       nzn = 0;
28273b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28284f1b2e48SStefano Zampini         PetscInt ns;
28294f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28304f1b2e48SStefano Zampini         nzn += ns;
28314f1b2e48SStefano Zampini       }
28324f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
28334f1b2e48SStefano Zampini       nzn = 0;
28343b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28354f1b2e48SStefano Zampini         PetscInt ns,*idxs;
28364f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
28374f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2838580bdb30SBarry Smith         ierr = PetscArraycpy(new_idxs+nzn,idxs,ns);CHKERRQ(ierr);
28394f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
28404f1b2e48SStefano Zampini         nzn += ns;
28414f1b2e48SStefano Zampini       }
28424f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
28434f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
28444f1b2e48SStefano Zampini     }
28454f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
28464f1b2e48SStefano Zampini   }
28474f1b2e48SStefano Zampini 
28483b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
2849820f2d46SBarry Smith   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
28503b03f7bbSStefano Zampini 
2851669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2852a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2853a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2854a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2855a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2856a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2857a198735bSStefano Zampini 
28581f4df5f7SStefano Zampini     if (pressures) {
28591f4df5f7SStefano Zampini       isused = pressures;
28601f4df5f7SStefano Zampini     } else {
28614edc6404Sstefano_zampini       isused = zerodiag_save;
28621f4df5f7SStefano Zampini     }
2863a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2864669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
28651ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
28661ae86dd6SStefano 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");
2867a198735bSStefano Zampini     n_isused = 0;
2868a198735bSStefano Zampini     if (isused) {
2869a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2870a198735bSStefano Zampini     }
2871ffc4695bSBarry Smith     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
2872a198735bSStefano Zampini     st = st-n_isused;
28731ae86dd6SStefano Zampini     if (n) {
2874a198735bSStefano Zampini       const PetscInt *gidxs;
2875a198735bSStefano Zampini 
28767dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2877a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2878a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2879a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2880a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2881a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
28821ae86dd6SStefano Zampini     } else {
2883a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2884a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2885a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2886a198735bSStefano Zampini     }
2887a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2888a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2889a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2890a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2891a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2892a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2893a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2894a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2895a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2896a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2897a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2898a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2899a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2900a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
29011ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29021ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29031ae86dd6SStefano Zampini   }
29044edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
29053b03f7bbSStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
29063b03f7bbSStefano Zampini   if (bzerodiag) {
29073b03f7bbSStefano Zampini     PetscInt i;
2908b3afcdbeSStefano Zampini 
29093b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
29103b03f7bbSStefano Zampini       ierr = ISDestroy(&bzerodiag[i]);CHKERRQ(ierr);
29113b03f7bbSStefano Zampini     }
29123b03f7bbSStefano Zampini     ierr = PetscFree(bzerodiag);CHKERRQ(ierr);
29133b03f7bbSStefano Zampini   }
29143b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
29153b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
29163b03f7bbSStefano Zampini 
29173b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
29183b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
2919820f2d46SBarry Smith   ierr = MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
29203b03f7bbSStefano Zampini 
29213b03f7bbSStefano Zampini project_b0:
2922aa0d93e9SStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2923b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
29243b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
29254f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
29264f1b2e48SStefano Zampini 
2927339f8db1SStefano Zampini     /* local change of basis for pressures */
2928339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
292997d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2930339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2931339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2932339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
2933aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
29344f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2935aa0d93e9SStefano Zampini       const PetscInt *idxs;
29364f1b2e48SStefano Zampini       PetscInt       nzs,j;
29374f1b2e48SStefano Zampini 
29383b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs);CHKERRQ(ierr);
29393b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29404f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
29414f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
29423b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
29434f1b2e48SStefano Zampini     }
2944339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2945e1b21442SStefano Zampini     ierr = MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
2946339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2947aa0d93e9SStefano Zampini     /* set identity by default */
2948aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
2949aa0d93e9SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES);CHKERRQ(ierr);
2950339f8db1SStefano Zampini     }
29519f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
29524f1b2e48SStefano 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);
2953339f8db1SStefano Zampini     /* set change on pressures */
29544f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
29554f1b2e48SStefano Zampini       PetscScalar    *array;
2956aa0d93e9SStefano Zampini       const PetscInt *idxs;
29574f1b2e48SStefano Zampini       PetscInt       nzs;
29584f1b2e48SStefano Zampini 
29593b03f7bbSStefano Zampini       ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs);CHKERRQ(ierr);
29603b03f7bbSStefano Zampini       ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
29614f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2962339f8db1SStefano Zampini         PetscScalar vals[2];
2963339f8db1SStefano Zampini         PetscInt    cols[2];
2964339f8db1SStefano Zampini 
2965339f8db1SStefano Zampini         cols[0] = idxs[i];
29664f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2967339f8db1SStefano Zampini         vals[0] = 1.;
2968b0f5fe93SStefano Zampini         vals[1] = 1.;
29694f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2970339f8db1SStefano Zampini       }
29714f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
29724f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29734f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29744f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
29754f1b2e48SStefano Zampini       /* store local idxs for p0 */
29764f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29773b03f7bbSStefano Zampini       ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2978339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
29794f1b2e48SStefano Zampini     }
2980339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2981339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29823b03f7bbSStefano Zampini 
2983a3df083aSStefano Zampini     /* project if needed */
2984a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29851dd7afcfSStefano Zampini       Mat M;
29861dd7afcfSStefano Zampini 
29871dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2988339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
29891dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
29901dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2991a3df083aSStefano Zampini     }
29924f1b2e48SStefano Zampini     /* store global idxs for p0 */
29934f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2994339f8db1SStefano Zampini   }
2995339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2996339f8db1SStefano Zampini   PetscFunctionReturn(0);
2997339f8db1SStefano Zampini }
2998339f8db1SStefano Zampini 
2999015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
3000efc2fbd9SStefano Zampini {
3001efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3002de9d7bd0SStefano Zampini   PetscScalar    *array;
3003efc2fbd9SStefano Zampini   PetscErrorCode ierr;
3004efc2fbd9SStefano Zampini 
3005efc2fbd9SStefano Zampini   PetscFunctionBegin;
3006efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
3007efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
30084f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
3009efc2fbd9SStefano Zampini   }
3010de9d7bd0SStefano Zampini   if (get) {
3011efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
3012ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE);CHKERRQ(ierr);
3013ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE);CHKERRQ(ierr);
3014efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
3015de9d7bd0SStefano Zampini   } else {
3016de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
301783df288dSJunchao Zhang     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE);CHKERRQ(ierr);
301883df288dSJunchao Zhang     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE);CHKERRQ(ierr);
3019de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
3020efc2fbd9SStefano Zampini   }
3021efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
3022efc2fbd9SStefano Zampini }
3023efc2fbd9SStefano Zampini 
3024c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
3025c263805aSStefano Zampini {
3026c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3027c263805aSStefano Zampini   PetscErrorCode ierr;
3028c263805aSStefano Zampini 
3029c263805aSStefano Zampini   PetscFunctionBegin;
3030c263805aSStefano Zampini   /* TODO: add error checking
3031c263805aSStefano Zampini     - avoid nested pop (or push) calls.
3032c263805aSStefano Zampini     - cannot push before pop.
30331c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
3034c263805aSStefano Zampini   */
30354f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3036efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
3037efc2fbd9SStefano Zampini   }
3038c263805aSStefano Zampini   if (pop) {
3039a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30404f1b2e48SStefano Zampini       IS       is_p0;
30414f1b2e48SStefano Zampini       MatReuse reuse;
3042c263805aSStefano Zampini 
3043c263805aSStefano Zampini       /* extract B_0 */
30444f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
30454f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
30464f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
30474f1b2e48SStefano Zampini       }
30484f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
30497dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
3050c263805aSStefano Zampini       /* remove rows and cols from local problem */
3051c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
305297d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
30534f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
30544f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
3055a3df083aSStefano Zampini     } else {
3056a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
3057a3df083aSStefano Zampini       PetscScalar *vals;
3058a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
3059a3df083aSStefano Zampini 
3060a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
3061a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
3062a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30630b5adadeSStefano Zampini         PetscInt *nnz;
3064a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
3065a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
3066a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3067331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
3068331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
3069331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
3070331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3071331e053bSStefano Zampini         }
3072331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
3073e1b21442SStefano Zampini         ierr = MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3074331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
3075331e053bSStefano Zampini       }
3076a3df083aSStefano Zampini 
3077a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3078a3df083aSStefano Zampini         PetscScalar *array;
3079a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3080a3df083aSStefano Zampini 
3081a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
3082a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3083a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3084a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
3085a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
3086a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
3087a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
3088a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
3089a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
3090a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
3091a3df083aSStefano Zampini         cum = 0;
3092a3df083aSStefano Zampini         for (j=0;j<n;j++) {
309322db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3094a3df083aSStefano Zampini             vals[cum] = array[j];
3095a3df083aSStefano Zampini             idxs_ins[cum] = j;
3096a3df083aSStefano Zampini             cum++;
3097a3df083aSStefano Zampini           }
3098a3df083aSStefano Zampini         }
3099a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
3100a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
3101a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3102a3df083aSStefano Zampini       }
3103a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3104a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3105a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
3106a3df083aSStefano Zampini     }
3107c263805aSStefano Zampini   } else { /* push */
3108a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
31094f1b2e48SStefano Zampini       PetscInt i;
31104f1b2e48SStefano Zampini 
31114f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
31124f1b2e48SStefano Zampini         PetscScalar *B0_vals;
31134f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
31144f1b2e48SStefano Zampini 
31154f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31164f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31177b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
31184f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
31194f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
31204f1b2e48SStefano Zampini       }
3121c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3122c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31236080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3124c263805aSStefano Zampini   }
3125c263805aSStefano Zampini   PetscFunctionReturn(0);
3126c263805aSStefano Zampini }
3127c263805aSStefano Zampini 
312808122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3129b1b3d7a2SStefano Zampini {
3130b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
313108122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
313208122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
313308122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
313408122e43SStefano Zampini   PetscScalar     *work,lwork;
313508122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
313608122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3137bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
31381b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3139f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
314008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
314108122e43SStefano Zampini   PetscReal       *rwork;
314208122e43SStefano Zampini #endif
3143b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3144b1b3d7a2SStefano Zampini 
3145b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3146b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3147af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3148bd2a564bSStefano 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);
314943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
315006a4e24aSStefano Zampini 
3151fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3152fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3153fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3154fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
31551575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3156fd14bc51SStefano Zampini   }
3157fd14bc51SStefano Zampini 
3158e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
31596080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %D (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);CHKERRQ(ierr);
3160e496cd5dSStefano Zampini   }
3161e496cd5dSStefano Zampini 
316208122e43SStefano Zampini   /* max size of subsets */
316308122e43SStefano Zampini   mss = 0;
316408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
316508122e43SStefano Zampini     PetscInt subset_size;
3166862806e4SStefano Zampini 
316708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
316808122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
316908122e43SStefano Zampini   }
317008122e43SStefano Zampini 
317108122e43SStefano Zampini   /* min/max and threshold */
317208122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3173f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
317408122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3175f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3176bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3177f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3178f6f667cfSStefano Zampini   }
317908122e43SStefano Zampini 
318008122e43SStefano Zampini   /* allocate lapack workspace */
318108122e43SStefano Zampini   cum = cum2 = 0;
318208122e43SStefano Zampini   maxneigs = 0;
318308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
318408122e43SStefano Zampini     PetscInt n,subset_size;
3185f6f667cfSStefano Zampini 
318608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
318708122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31889162d606SStefano Zampini     cum += subset_size;
31899162d606SStefano Zampini     cum2 += subset_size*n;
319008122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
319108122e43SStefano Zampini   }
31927ebab0bbSStefano Zampini   lwork = 0;
319308122e43SStefano Zampini   if (mss) {
3194bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
31957ebab0bbSStefano Zampini       PetscScalar  sdummy = 0.;
319608122e43SStefano Zampini       PetscBLASInt B_itype = 1;
31977ebab0bbSStefano Zampini       PetscBLASInt B_N = mss, idummy = 0;
31987ebab0bbSStefano Zampini       PetscReal    rdummy = 0.,zero = 0.0;
31994c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
320008122e43SStefano Zampini 
320108122e43SStefano Zampini       B_lwork = -1;
32027ebab0bbSStefano Zampini       /* some implementations may complain about NULL pointers, even if we are querying */
32037ebab0bbSStefano Zampini       S = &sdummy;
32047ebab0bbSStefano Zampini       St = &sdummy;
32057ebab0bbSStefano Zampini       eigs = &rdummy;
32067ebab0bbSStefano Zampini       eigv = &sdummy;
32077ebab0bbSStefano Zampini       B_iwork = &idummy;
32087ebab0bbSStefano Zampini       B_ifail = &idummy;
3209d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32107ebab0bbSStefano Zampini       rwork = &rdummy;
3211d1710679SStefano Zampini #endif
32128bec7fa6SStefano Zampini       thresh = 1.0;
321308122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
321408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
321508122e43SStefano 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));
321608122e43SStefano Zampini #else
321708122e43SStefano 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));
321808122e43SStefano Zampini #endif
321908122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
322008122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3221bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
322208122e43SStefano Zampini   }
322308122e43SStefano Zampini 
322408122e43SStefano Zampini   nv = 0;
3225d62866d3SStefano 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) */
3226d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
322708122e43SStefano Zampini   }
32284c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3229f6f667cfSStefano Zampini   if (allocated_S_St) {
3230f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3231f6f667cfSStefano Zampini   }
3232f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
323308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
323408122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
323508122e43SStefano Zampini #endif
32369162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
32379162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
32389162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
323908122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
32409162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
3241580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs);CHKERRQ(ierr);
324208122e43SStefano Zampini 
324308122e43SStefano Zampini   maxneigs = 0;
324472b8c272SStefano Zampini   cum = cumarray = 0;
32459162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
32469162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3247d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
324808122e43SStefano Zampini     const PetscInt *idxs;
324908122e43SStefano Zampini 
3250d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
325108122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
325208122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
325308122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
325408122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
32559162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
32569162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
325708122e43SStefano Zampini     }
3258d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
325908122e43SStefano Zampini   }
326008122e43SStefano Zampini 
326108122e43SStefano Zampini   if (mss) { /* multilevel */
326208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
326308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
326408122e43SStefano Zampini   }
326508122e43SStefano Zampini 
3266bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3267bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
326808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
326908122e43SStefano Zampini     const PetscInt *idxs;
32709d54b7f4SStefano Zampini     PetscReal      upper,lower;
3271862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
327208122e43SStefano Zampini     PetscBLASInt   B_N;
3273aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3274bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
327508122e43SStefano Zampini 
32769d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
32779d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3278bd2a564bSStefano Zampini       lower = uthresh;
32799d54b7f4SStefano Zampini     } else {
3280bd2a564bSStefano Zampini       if (!sub_schurs->is_posdef) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3281bd2a564bSStefano Zampini       upper = 1./uthresh;
32829d54b7f4SStefano Zampini       lower = 0.;
32839d54b7f4SStefano Zampini     }
3284862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3285ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3286f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3287bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3288bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3289bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3290bd2a564bSStefano Zampini       Mat T;
3291bd2a564bSStefano Zampini 
3292bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3293bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
3294bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T);CHKERRQ(ierr);
3295bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3296bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3297bd2a564bSStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T);CHKERRQ(ierr);
3298bd2a564bSStefano Zampini           ierr = MatScale(T,-1.0);CHKERRQ(ierr);
3299bd2a564bSStefano Zampini           ierr = MatDestroy(&T);CHKERRQ(ierr);
3300bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3301bd2a564bSStefano Zampini             PetscInt       nz,k;
3302bd2a564bSStefano Zampini             const PetscInt *idxs;
3303bd2a564bSStefano Zampini 
3304bd2a564bSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz);CHKERRQ(ierr);
3305bd2a564bSStefano Zampini             ierr = ISGetIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3306bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3307bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3308bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3309bd2a564bSStefano Zampini             }
3310bd2a564bSStefano Zampini             ierr = ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs);CHKERRQ(ierr);
3311bd2a564bSStefano Zampini           }
3312bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3313bd2a564bSStefano Zampini           break;
3314bd2a564bSStefano Zampini         }
3315bd2a564bSStefano Zampini       }
3316bd2a564bSStefano Zampini     }
3317bd2a564bSStefano Zampini 
3318f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3319bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3320aff50787SStefano Zampini         PetscInt j,k;
3321580bdb30SBarry Smith         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */
3322580bdb30SBarry Smith           ierr = PetscArrayzero(S,subset_size*subset_size);CHKERRQ(ierr);
3323580bdb30SBarry Smith           ierr = PetscArrayzero(St,subset_size*subset_size);CHKERRQ(ierr);
332408122e43SStefano Zampini         }
332508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3326aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3327aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3328aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3329aff50787SStefano Zampini           }
333008122e43SStefano Zampini         }
333108122e43SStefano Zampini       } else {
3332580bdb30SBarry Smith         ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3333580bdb30SBarry Smith         ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
333408122e43SStefano Zampini       }
33358bec7fa6SStefano Zampini     } else {
3336f6f667cfSStefano Zampini       S = Sarray + cumarray;
3337f6f667cfSStefano Zampini       St = Starray + cumarray;
33388bec7fa6SStefano Zampini     }
3339aff50787SStefano Zampini     /* see if we can save some work */
3340b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3341580bdb30SBarry Smith       ierr = PetscArraycmp(S,St,subset_size*subset_size,&same_data);CHKERRQ(ierr);
3342aff50787SStefano Zampini     }
3343aff50787SStefano Zampini 
3344b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3345aff50787SStefano Zampini       B_neigs = 0;
3346aff50787SStefano Zampini     } else {
3347bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
334808122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3349f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
33504c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
33519552c7c7SStefano Zampini         PetscInt     nmin_s;
3352bd2a564bSStefano Zampini         PetscBool    compute_range;
3353bd2a564bSStefano Zampini 
33549036ceccSStefano Zampini         B_neigs = 0;
3355bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3356bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
335708122e43SStefano Zampini 
3358fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
33599036ceccSStefano Zampini           PetscInt nc = 0;
3360d16cbb6bSStefano Zampini 
33619036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
33629036ceccSStefano Zampini             ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc);CHKERRQ(ierr);
33639036ceccSStefano Zampini           }
33646080607fSStefano 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);
3365b7ab4a40SStefano Zampini         }
3366b7ab4a40SStefano Zampini 
336708122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3368b7ab4a40SStefano Zampini         if (compute_range) {
3369d16cbb6bSStefano Zampini 
3370d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3371bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
337208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33739d54b7f4SStefano 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));
337408122e43SStefano Zampini #else
33759d54b7f4SStefano 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));
337608122e43SStefano Zampini #endif
337743371fb9SStefano Zampini             ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3378bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33799036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3380bd2a564bSStefano Zampini             PetscReal bb[2];
3381bd2a564bSStefano Zampini 
3382bd2a564bSStefano Zampini             ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL);CHKERRQ(ierr);
3383bd2a564bSStefano Zampini             switch (recipe) {
3384bd2a564bSStefano Zampini             case 0:
3385bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3386bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3387bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3388bd2a564bSStefano 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));
3389bd2a564bSStefano Zampini #else
3390bd2a564bSStefano 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));
3391bd2a564bSStefano Zampini #endif
339243371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3393bd2a564bSStefano Zampini               break;
3394bd2a564bSStefano Zampini             case 1:
3395bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3396bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3397bd2a564bSStefano 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));
3398bd2a564bSStefano Zampini #else
3399bd2a564bSStefano 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));
3400bd2a564bSStefano Zampini #endif
340143371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3402bd2a564bSStefano Zampini               if (!scal) {
34039036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3404bd2a564bSStefano Zampini 
3405aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
3406580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3407580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3408bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3409bd2a564bSStefano 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));
3410bd2a564bSStefano Zampini #else
3411bd2a564bSStefano 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));
3412bd2a564bSStefano Zampini #endif
341343371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3414bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3415bd2a564bSStefano Zampini               }
3416bd2a564bSStefano Zampini               break;
34179036ceccSStefano Zampini             case 2:
34189036ceccSStefano Zampini               if (scal) {
34199036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
34209036ceccSStefano Zampini                 bb[1] = 0;
34219036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34229036ceccSStefano 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));
34239036ceccSStefano Zampini #else
34249036ceccSStefano 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));
34259036ceccSStefano Zampini #endif
342643371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34279036ceccSStefano Zampini               } else {
34289036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34299036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
34309036ceccSStefano Zampini 
34319036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
34329036ceccSStefano Zampini                 if (lthresh > 0.0) {
34339036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
34349036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
34359036ceccSStefano Zampini 
34369036ceccSStefano Zampini                   import = PETSC_TRUE;
34379036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34389036ceccSStefano 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));
34399036ceccSStefano Zampini #else
34409036ceccSStefano 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));
34419036ceccSStefano Zampini #endif
344243371fb9SStefano Zampini                   ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34439036ceccSStefano Zampini                 }
34449036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
34459036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34469036ceccSStefano Zampini                 if (import) {
3447580bdb30SBarry Smith                   ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3448580bdb30SBarry Smith                   ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34499036ceccSStefano Zampini                 }
34509036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34519036ceccSStefano 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));
34529036ceccSStefano Zampini #else
34539036ceccSStefano 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));
34549036ceccSStefano Zampini #endif
345543371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34569036ceccSStefano Zampini                 B_neigs += B_neigs2;
34579036ceccSStefano Zampini               }
34589036ceccSStefano Zampini               break;
34599036ceccSStefano Zampini             case 3:
34609036ceccSStefano Zampini               if (scal) {
34619036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL);CHKERRQ(ierr);
34629036ceccSStefano Zampini               } else {
34639036ceccSStefano Zampini                 ierr = PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL);CHKERRQ(ierr);
34649036ceccSStefano Zampini               }
34659036ceccSStefano Zampini               if (!scal) {
34669036ceccSStefano Zampini                 bb[0] = uthresh;
34679036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34689036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34699036ceccSStefano 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));
34709036ceccSStefano Zampini #else
34719036ceccSStefano 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));
34729036ceccSStefano Zampini #endif
347343371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34749036ceccSStefano Zampini               }
34759036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34769036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34779036ceccSStefano Zampini 
34789036ceccSStefano Zampini                 B_IL = 1;
34799036ceccSStefano Zampini                 ierr = PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU);CHKERRQ(ierr);
3480580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3481580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
34829036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34839036ceccSStefano 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));
34849036ceccSStefano Zampini #else
34859036ceccSStefano 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));
34869036ceccSStefano Zampini #endif
348743371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
34889036ceccSStefano Zampini                 B_neigs += B_neigs2;
34899036ceccSStefano Zampini               }
34909036ceccSStefano Zampini               break;
349148cebe81SStefano Zampini             case 4:
349248cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
349348cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
349448cebe81SStefano 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));
349548cebe81SStefano Zampini #else
349648cebe81SStefano 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));
349748cebe81SStefano Zampini #endif
349843371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
349948cebe81SStefano Zampini               {
350048cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
350148cebe81SStefano Zampini 
350248cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
3503580bdb30SBarry Smith                 ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3504580bdb30SBarry Smith                 ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
350548cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
350648cebe81SStefano 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));
350748cebe81SStefano Zampini #else
350848cebe81SStefano 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));
350948cebe81SStefano Zampini #endif
351043371fb9SStefano Zampini                 ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
351148cebe81SStefano Zampini                 B_neigs += B_neigs2;
351248cebe81SStefano Zampini               }
351348cebe81SStefano Zampini               break;
351480db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
351580db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
351680db8efeSStefano 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));
351780db8efeSStefano Zampini #else
351880db8efeSStefano 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));
351980db8efeSStefano Zampini #endif
352043371fb9SStefano Zampini               ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
352180db8efeSStefano Zampini               {
352280db8efeSStefano Zampini                 PetscInt e,k,ne;
352380db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
352480db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
352580db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
352680db8efeSStefano Zampini                     eigs[ne] = eigs[e];
352780db8efeSStefano Zampini                     ne++;
352880db8efeSStefano Zampini                   }
352980db8efeSStefano Zampini                 }
3530580bdb30SBarry Smith                 ierr = PetscArraycpy(eigv,S,B_N*ne);CHKERRQ(ierr);
353180db8efeSStefano Zampini                 B_neigs = ne;
353280db8efeSStefano Zampini               }
353380db8efeSStefano Zampini               break;
3534bd2a564bSStefano Zampini             default:
3535bd2a564bSStefano Zampini               SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe);
3536bd2a564bSStefano Zampini             }
3537bd2a564bSStefano Zampini           }
3538bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3539d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3540d16cbb6bSStefano Zampini           B_IL = 1;
3541d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
35429d54b7f4SStefano 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));
3543d16cbb6bSStefano Zampini #else
35449d54b7f4SStefano 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));
3545d16cbb6bSStefano Zampini #endif
354643371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
3547b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3548b7ab4a40SStefano Zampini           PetscInt k;
3549b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3550b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3551b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3552b7ab4a40SStefano Zampini           nmin = nmax;
3553580bdb30SBarry Smith           ierr = PetscArrayzero(eigv,subset_size*nmax);CHKERRQ(ierr);
3554b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3555b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3556b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3557b7ab4a40SStefano Zampini           }
3558d16cbb6bSStefano Zampini         }
355908122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
356008122e43SStefano Zampini         if (B_ierr) {
35616c4ed002SBarry 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);
35626c4ed002SBarry 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);
35636c4ed002SBarry 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);
356408122e43SStefano Zampini         }
356508122e43SStefano Zampini 
356608122e43SStefano Zampini         if (B_neigs > nmax) {
3567fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35686080607fSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %D.\n",B_neigs,nmax);CHKERRQ(ierr);
3569fd14bc51SStefano Zampini           }
3570bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
357108122e43SStefano Zampini           B_neigs = nmax;
357208122e43SStefano Zampini         }
357308122e43SStefano Zampini 
35749552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35759552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35769036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
357708122e43SStefano Zampini 
35789d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3579bd2a564bSStefano Zampini             if (scal) {
3580bd2a564bSStefano Zampini               B_IU = nmin_s;
3581bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3582bd2a564bSStefano Zampini             } else {
3583f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35849d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3585bd2a564bSStefano Zampini             }
35869d54b7f4SStefano Zampini           } else {
35879d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35889d54b7f4SStefano Zampini             B_IU = nmin_s;
35899d54b7f4SStefano Zampini           }
3590fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
35916080607fSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %D. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);CHKERRQ(ierr);
3592fd14bc51SStefano Zampini           }
3593bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35941ae86dd6SStefano Zampini             PetscInt j,k;
359508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35961ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35971ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35981ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
359908122e43SStefano Zampini               }
360008122e43SStefano Zampini             }
360108122e43SStefano Zampini           } else {
3602580bdb30SBarry Smith             ierr = PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
3603580bdb30SBarry Smith             ierr = PetscArraycpy(St,Starray+cumarray,subset_size*subset_size);CHKERRQ(ierr);
360408122e43SStefano Zampini           }
360508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
360608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36079d54b7f4SStefano 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));
360808122e43SStefano Zampini #else
36099d54b7f4SStefano 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));
361008122e43SStefano Zampini #endif
361143371fb9SStefano Zampini           ierr = PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0);CHKERRQ(ierr);
361208122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
361308122e43SStefano Zampini           B_neigs += B_neigs2;
361408122e43SStefano Zampini         }
361508122e43SStefano Zampini         if (B_ierr) {
36166c4ed002SBarry 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);
36176c4ed002SBarry 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);
36186c4ed002SBarry 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);
361908122e43SStefano Zampini         }
3620fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3621ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
362208122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
362308122e43SStefano Zampini             if (eigs[j] == 0.0) {
3624ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
362508122e43SStefano Zampini             } else {
36269d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3627ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
36289d54b7f4SStefano Zampini               } else {
36299d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
36309d54b7f4SStefano Zampini               }
3631fd14bc51SStefano Zampini             }
363208122e43SStefano Zampini           }
363308122e43SStefano Zampini         }
3634bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3635aff50787SStefano Zampini     }
36366c3e6151SStefano Zampini     /* change the basis back to the original one */
36376c3e6151SStefano Zampini     if (sub_schurs->change) {
363872b8c272SStefano Zampini       Mat change,phi,phit;
36396c3e6151SStefano Zampini 
364003dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
36416c3e6151SStefano Zampini         PetscInt ii;
36426c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
36436c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36446c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3645684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3646684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3647684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3648684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3649684229deSStefano Zampini #else
36506c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3651684229deSStefano Zampini #endif
36526c3e6151SStefano Zampini           }
36536c3e6151SStefano Zampini         }
36546c3e6151SStefano Zampini       }
365572b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
36566c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
365772b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
36586c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
36596c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
36606c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
36616c3e6151SStefano Zampini     }
36628bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36638bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36649162d606SStefano Zampini     if (B_neigs) {
3665580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size);CHKERRQ(ierr);
3666fd14bc51SStefano Zampini 
3667fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36689552c7c7SStefano Zampini         PetscInt ii;
36699552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3670ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
36719552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3672ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3673ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3674ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3675ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3676ac47001eSStefano Zampini #else
3677ac47001eSStefano 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);
3678ac47001eSStefano Zampini #endif
36799552c7c7SStefano Zampini           }
36809552c7c7SStefano Zampini         }
3681fd14bc51SStefano Zampini       }
3682580bdb30SBarry Smith       ierr = PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size);CHKERRQ(ierr);
36839162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36849162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36859162d606SStefano Zampini       cum++;
368608122e43SStefano Zampini     }
368708122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
368808122e43SStefano Zampini     /* shift for next computation */
368908122e43SStefano Zampini     cumarray += subset_size*subset_size;
369008122e43SStefano Zampini   }
3691fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3692fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3693fd14bc51SStefano Zampini   }
369408122e43SStefano Zampini 
369508122e43SStefano Zampini   if (mss) {
369608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
369708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3698f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3699f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3700f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
370108122e43SStefano Zampini   }
3702f6f667cfSStefano Zampini   if (allocated_S_St) {
3703f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3704f6f667cfSStefano Zampini   }
3705f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
370608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
370708122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
370808122e43SStefano Zampini #endif
370908122e43SStefano Zampini   if (pcbddc->dbg_flag) {
37101b968477SStefano Zampini     PetscInt maxneigs_r;
3711820f2d46SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
37126080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %D\n",maxneigs_r);CHKERRQ(ierr);
371308122e43SStefano Zampini   }
371443371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
371508122e43SStefano Zampini   PetscFunctionReturn(0);
371608122e43SStefano Zampini }
3717b1b3d7a2SStefano Zampini 
3718c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3719c8587f34SStefano Zampini {
37208629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3721c8587f34SStefano Zampini   PetscErrorCode ierr;
3722c8587f34SStefano Zampini 
3723c8587f34SStefano Zampini   PetscFunctionBegin;
3724f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
37255e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3726c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3727c8587f34SStefano Zampini 
3728684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
37290fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3730684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3731c8587f34SStefano Zampini 
37328629588bSStefano Zampini   /*
37338629588bSStefano Zampini      Setup local correction and local part of coarse basis.
37348629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
37358629588bSStefano Zampini   */
373647f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
37378629588bSStefano Zampini 
37388629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
37398629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
37408629588bSStefano Zampini 
37418629588bSStefano Zampini   /* free */
37428629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3743c8587f34SStefano Zampini   PetscFunctionReturn(0);
3744c8587f34SStefano Zampini }
3745c8587f34SStefano Zampini 
3746674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3747674ae819SStefano Zampini {
3748674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3749674ae819SStefano Zampini   PetscErrorCode ierr;
3750674ae819SStefano Zampini 
3751674ae819SStefano Zampini   PetscFunctionBegin;
3752674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
375330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3754674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3755785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3756674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3757f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3758f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3759785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
376063602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
376163602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3762674ae819SStefano Zampini   PetscFunctionReturn(0);
3763674ae819SStefano Zampini }
3764674ae819SStefano Zampini 
3765674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3766674ae819SStefano Zampini {
3767674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37684f1b2e48SStefano Zampini   PetscInt       i;
3769674ae819SStefano Zampini   PetscErrorCode ierr;
3770674ae819SStefano Zampini 
3771674ae819SStefano Zampini   PetscFunctionBegin;
37721e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
37731e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3774a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3775b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3776674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
377716909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
37781dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3779674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3780669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3781fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
37829326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
37834f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37844f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
37854f1b2e48SStefano Zampini   }
3786e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37874f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3788e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3789c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37908af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37911c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3792674ae819SStefano Zampini   PetscFunctionReturn(0);
3793674ae819SStefano Zampini }
3794674ae819SStefano Zampini 
3795674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3796674ae819SStefano Zampini {
3797674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3798674ae819SStefano Zampini   PetscErrorCode ierr;
3799674ae819SStefano Zampini 
3800674ae819SStefano Zampini   PetscFunctionBegin;
3801674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
380258da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3803ca92afb2SStefano Zampini     PetscScalar *array;
380406656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
380506656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
380658da7f69SStefano Zampini   }
3807674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3808674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
380915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
381015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3811674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3812674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3813674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
381406656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3815674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3816674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38178ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3818674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3819674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3820674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38219326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
38229326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
38239326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3824f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3825727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
38260e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3827f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
382870cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
382981d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
38300369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
38311dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
38324f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
38338b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3834ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3835ca92afb2SStefano Zampini     PetscInt i;
3836ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3837ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3838ca92afb2SStefano Zampini     }
3839ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3840ca92afb2SStefano Zampini   }
38414f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3842674ae819SStefano Zampini   PetscFunctionReturn(0);
3843674ae819SStefano Zampini }
3844674ae819SStefano Zampini 
3845f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
38466bfb1811SStefano Zampini {
38476bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38486bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
38496bfb1811SStefano Zampini   VecType        impVecType;
38504f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
38516bfb1811SStefano Zampini   PetscErrorCode ierr;
38526bfb1811SStefano Zampini 
38536bfb1811SStefano Zampini   PetscFunctionBegin;
38544f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3855b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
38566bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3857e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3858e7b262bdSStefano Zampini   /* R nodes */
3859e7b262bdSStefano Zampini   old_size = -1;
3860e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3861e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3862e7b262bdSStefano Zampini   }
3863e7b262bdSStefano Zampini   if (n_R != old_size) {
3864e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3865e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
38666bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
38676bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
38686bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
38696bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3870e7b262bdSStefano Zampini   }
3871e7b262bdSStefano Zampini   /* local primal dofs */
3872e7b262bdSStefano Zampini   old_size = -1;
3873e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3874e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3875e7b262bdSStefano Zampini   }
3876e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3877e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
387883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3879e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
38806bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3881e7b262bdSStefano Zampini   }
3882e7b262bdSStefano Zampini   /* local explicit constraints */
3883e7b262bdSStefano Zampini   old_size = -1;
3884e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3885e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3886e7b262bdSStefano Zampini   }
3887e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3888e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
388983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
389083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
389183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
389283b7ccabSStefano Zampini   }
38936bfb1811SStefano Zampini   PetscFunctionReturn(0);
38946bfb1811SStefano Zampini }
38956bfb1811SStefano Zampini 
389647f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
389788ebb749SStefano Zampini {
389825084f0cSStefano Zampini   PetscErrorCode  ierr;
389925084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
390088ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
390188ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3902d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
390325084f0cSStefano Zampini   /* submatrices of local problem */
390480677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
390506656605SStefano Zampini   /* submatrices of local coarse problem */
390606656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
390725084f0cSStefano Zampini   /* working matrices */
390806656605SStefano Zampini   Mat             C_CR;
390925084f0cSStefano Zampini   /* additional working stuff */
391006656605SStefano Zampini   PC              pc_R;
3911c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
39125cbda25cSStefano Zampini   Vec             dummy_vec;
39137ebab0bbSStefano Zampini   PetscBool       isLU,isCHOL,need_benign_correction,sparserhs;
391425084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
391506656605SStefano Zampini   PetscScalar     *work;
391606656605SStefano Zampini   PetscInt        *idx_V_B;
3917ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
391806656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
391906656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
392088ebb749SStefano Zampini 
392188ebb749SStefano Zampini   PetscFunctionBegin;
39229a962809SStefano 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");
392343371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
3924ffd830a3SStefano Zampini 
3925ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3926b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39274f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3928b371cd4fSStefano Zampini   n_B = pcis->n_B;
3929b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
393088ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
393188ebb749SStefano Zampini 
393288ebb749SStefano Zampini   /* vertices in boundary numbering */
3933785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
39340e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
39356080607fSStefano Zampini   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",n_vertices,i);
393688ebb749SStefano Zampini 
393706656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3938019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
393906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
3940ad16ce7aSStefano Zampini   ierr = MatDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
394106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
3942ad16ce7aSStefano Zampini   ierr = MatDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
394306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
3944ad16ce7aSStefano Zampini   ierr = MatDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
394506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
3946ad16ce7aSStefano Zampini   ierr = MatDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
394706656605SStefano Zampini 
394806656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
394906656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
39502958b453SStefano Zampini   ierr = PCSetUp(pc_R);CHKERRQ(ierr);
395106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
395206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3953ffd830a3SStefano Zampini   lda_rhs = n_R;
3954a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
39557ebab0bbSStefano Zampini   if (isLU || isCHOL) {
395606656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3957b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3958df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3959d62866d3SStefano Zampini     MatFactorType      type;
3960d62866d3SStefano Zampini 
3961df4d28bfSStefano Zampini     F = reuse_solver->F;
39626816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3963d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
39647ebab0bbSStefano Zampini     if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE;
3965ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
396622db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
39677ebab0bbSStefano Zampini   } else F = NULL;
396806656605SStefano Zampini 
3969c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3970c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3971c58f9fdbSStefano Zampini   if (F) {
3972ea799195SBarry Smith     MatSolverType solver;
3973c58f9fdbSStefano Zampini 
39743ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3975c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3976c58f9fdbSStefano Zampini   }
3977c58f9fdbSStefano Zampini 
3978ffd830a3SStefano Zampini   /* allocate workspace */
3979ffd830a3SStefano Zampini   n = 0;
3980ffd830a3SStefano Zampini   if (n_constraints) {
3981ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3982ffd830a3SStefano Zampini   }
3983ffd830a3SStefano Zampini   if (n_vertices) {
3984ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3985ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3986ffd830a3SStefano Zampini   }
39872a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39882a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39892a3a6641Sstefano_zampini   }
3990ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3991ffd830a3SStefano Zampini 
39925cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39935cbda25cSStefano Zampini   dummy_vec = NULL;
39945cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
3995c72cccf8SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec);CHKERRQ(ierr);
3996c72cccf8SStefano Zampini     ierr = VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE);CHKERRQ(ierr);
3997c72cccf8SStefano Zampini     ierr = VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name);CHKERRQ(ierr);
39985cbda25cSStefano Zampini   }
39995cbda25cSStefano Zampini 
40007ebab0bbSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
40017ebab0bbSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
40027ebab0bbSStefano Zampini 
400388ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
400488ebb749SStefano Zampini   if (n_constraints) {
4005837cedc9SStefano Zampini     Mat         M3,C_B;
400606656605SStefano Zampini     IS          is_aux;
400706656605SStefano Zampini 
400825084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
400925084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
40107dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
40117dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
401288ebb749SStefano Zampini 
401380677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
401480677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
4015c58f9fdbSStefano Zampini     if (!sparserhs) {
4016580bdb30SBarry Smith       ierr = PetscArrayzero(work,lda_rhs*n_constraints);CHKERRQ(ierr);
401788ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
401806656605SStefano Zampini         const PetscScalar *row_cmat_values;
401906656605SStefano Zampini         const PetscInt    *row_cmat_indices;
402006656605SStefano Zampini         PetscInt          size_of_constraint,j;
402188ebb749SStefano Zampini 
402206656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402306656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
4024ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
402506656605SStefano Zampini         }
402606656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
402706656605SStefano Zampini       }
4028c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
4029c58f9fdbSStefano Zampini     } else {
4030c58f9fdbSStefano Zampini       Mat tC_CR;
4031c58f9fdbSStefano Zampini 
4032c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4033c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
4034c58f9fdbSStefano Zampini         PetscScalar *aa;
4035c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
4036c58f9fdbSStefano Zampini         PetscBool   done;
4037c58f9fdbSStefano Zampini 
4038c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
403913903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4040c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
4041c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
4042c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
404313903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4044c58f9fdbSStefano Zampini       } else {
4045c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
4046c58f9fdbSStefano Zampini         tC_CR = C_CR;
4047c58f9fdbSStefano Zampini       }
4048c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
4049c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
4050c58f9fdbSStefano Zampini     }
4051ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
405206656605SStefano Zampini     if (F) {
4053a3df083aSStefano Zampini       if (need_benign_correction) {
4054df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4055a3df083aSStefano Zampini 
405672b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
4057580bdb30SBarry Smith         ierr = PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n);CHKERRQ(ierr);
4058a3df083aSStefano Zampini       }
4059c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
4060a3df083aSStefano Zampini       if (need_benign_correction) {
4061a3df083aSStefano Zampini         PetscScalar        *marr;
4062df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4063a3df083aSStefano Zampini 
4064a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
40655cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40665cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40675cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40685cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40695cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40705cbda25cSStefano Zampini           }
40715cbda25cSStefano Zampini         } else {
4072a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
4073a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40745cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4075a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4076a3df083aSStefano Zampini           }
40775cbda25cSStefano Zampini         }
4078a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
4079a3df083aSStefano Zampini       }
408006656605SStefano Zampini     } else {
408180677318SStefano Zampini       PetscScalar *marr;
408280677318SStefano Zampini 
408380677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
408406656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
4085ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4086ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
408706656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4088c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
408906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
409006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
409106656605SStefano Zampini       }
409280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
409306656605SStefano Zampini     }
4094c58f9fdbSStefano Zampini     if (sparserhs) {
4095c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
4096c58f9fdbSStefano Zampini     }
4097c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
409880677318SStefano Zampini     if (!pcbddc->switch_static) {
409980677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
410080677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4101*ab2d12f3SJunchao Zhang         Vec r, b;
4102*ab2d12f3SJunchao Zhang         ierr = MatDenseGetColumnVecRead(local_auxmat2_R,i,&r);CHKERRQ(ierr);
4103*ab2d12f3SJunchao Zhang         ierr = MatDenseGetColumnVec(pcbddc->local_auxmat2,i,&b);CHKERRQ(ierr);
4104*ab2d12f3SJunchao Zhang         ierr = VecScatterBegin(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4105*ab2d12f3SJunchao Zhang         ierr = VecScatterEnd(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4106*ab2d12f3SJunchao Zhang         ierr = MatDenseRestoreColumnVec(pcbddc->local_auxmat2,i,&b);CHKERRQ(ierr);
4107*ab2d12f3SJunchao Zhang         ierr = MatDenseRestoreColumnVecRead(local_auxmat2_R,i,&r);CHKERRQ(ierr);
410880677318SStefano Zampini       }
410972b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
411080677318SStefano Zampini     } else {
4111ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4112ffd830a3SStefano Zampini         IS dummy;
4113ffd830a3SStefano Zampini 
4114ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
41157dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
4116ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
4117ffd830a3SStefano Zampini       } else {
411880677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
411980677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4120ffd830a3SStefano Zampini       }
412125084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
412280677318SStefano Zampini     }
412380677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
412480677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1}  */
412580677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
412680677318SStefano Zampini     if (isCHOL) {
412780677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
412880677318SStefano Zampini     } else {
412925084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
413080677318SStefano Zampini     }
4131837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
413280677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
4133837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
413472b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
4135837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
4136837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
4137f4ddd8eeSStefano Zampini   }
4138fc227af8SStefano Zampini 
4139fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
414088ebb749SStefano Zampini   if (n_vertices) {
41417ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41427ebab0bbSStefano Zampini     PetscBool oldpin;
41437ebab0bbSStefano Zampini #endif
41447ebab0bbSStefano Zampini     PetscBool isaij;
414506656605SStefano Zampini     IS        is_aux;
41463a50541eSStefano Zampini 
4147b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
41486816873aSStefano Zampini       IS tis;
41496816873aSStefano Zampini 
41506816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
41516816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
41526816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
41536816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
41546816873aSStefano Zampini     } else {
41553a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
41566816873aSStefano Zampini     }
41577ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4158b470e4b4SRichard Tran Mills     oldpin = pcbddc->local_mat->boundtocpu;
41597ebab0bbSStefano Zampini #endif
4160b470e4b4SRichard Tran Mills     ierr = MatBindToCPU(pcbddc->local_mat,PETSC_TRUE);CHKERRQ(ierr);
41617dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
41627dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
41637ebab0bbSStefano Zampini     ierr = PetscObjectBaseTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isaij);CHKERRQ(ierr);
41647ebab0bbSStefano Zampini     if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */
4165c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
41667ebab0bbSStefano Zampini     }
41677dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
41687ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4169b470e4b4SRichard Tran Mills     ierr = MatBindToCPU(pcbddc->local_mat,oldpin);CHKERRQ(ierr);
41707ebab0bbSStefano Zampini #endif
417125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
417288ebb749SStefano Zampini   }
417388ebb749SStefano Zampini 
417488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4175f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
417606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
417706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
417806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
417906656605SStefano Zampini     }
4180f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
418106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
418206656605SStefano Zampini       PetscScalar *marray;
418306656605SStefano Zampini 
418406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
418506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
4186f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4187f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4188f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4189f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
4190f4ddd8eeSStefano Zampini     }
4191f4ddd8eeSStefano Zampini   }
419206656605SStefano Zampini 
4193f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4194a6e023c1Sstefano_zampini     PetscScalar *marr;
419588ebb749SStefano Zampini 
4196a6e023c1Sstefano_zampini     /* memory size */
419706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4198a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4199a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
4200a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
4201a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
4202a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
42038eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4204a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
4205a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
420688ebb749SStefano Zampini     }
42073301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
4208a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
4209a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
42108eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4211a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
421288ebb749SStefano Zampini       }
421388ebb749SStefano Zampini     } else {
4214c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
4215c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
42161b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4217c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
4218c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4219c0553b1fSStefano Zampini       }
422088ebb749SStefano Zampini     }
422106656605SStefano Zampini   }
4222019a44ceSStefano Zampini 
422306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
42244f1b2e48SStefano Zampini   p0_lidx_I = NULL;
42254f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4226d12edf2fSStefano Zampini     const PetscInt *idxs;
4227d12edf2fSStefano Zampini 
4228d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
42294f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
42304f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
42314f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
42324f1b2e48SStefano Zampini     }
4233d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
4234d12edf2fSStefano Zampini   }
4235d16cbb6bSStefano Zampini 
423606656605SStefano Zampini   /* vertices */
423706656605SStefano Zampini   if (n_vertices) {
4238c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
423916f15bc4SStefano Zampini 
4240af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
424104708bb6SStefano Zampini 
424216f15bc4SStefano Zampini     if (n_R) {
424314393ed6SStefano Zampini       Mat               A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
424406656605SStefano Zampini       PetscBLASInt      B_N,B_one = 1;
42451683a169SBarry Smith       const PetscScalar *x;
42461683a169SBarry Smith       PetscScalar       *y;
424706656605SStefano Zampini 
424821eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
424914393ed6SStefano Zampini       if (need_benign_correction) {
425014393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
425114393ed6SStefano Zampini         IS                     is_p0;
425214393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
425314393ed6SStefano Zampini 
425414393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
425514393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
425614393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
42576080607fSStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %D != %D",n,pcbddc->benign_n);
425814393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
425914393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
42607dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
426114393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
426214393ed6SStefano Zampini       }
426314393ed6SStefano Zampini 
4264c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4265c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4266ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
4267af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4268ffd830a3SStefano Zampini         } else {
4269ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4270ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4271ca92afb2SStefano Zampini           PetscInt       n;
4272ca92afb2SStefano Zampini           PetscBool      flg_row;
4273ffd830a3SStefano Zampini 
4274ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
4275580bdb30SBarry Smith           ierr = PetscArrayzero(array,lda_rhs*n_vertices);CHKERRQ(ierr);
42769d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
4277ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4278ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
4279ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4280ca92afb2SStefano Zampini             PetscInt j;
4281ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4282ffd830a3SStefano Zampini           }
4283ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4284ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4285ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
4286ffd830a3SStefano Zampini         }
4287a3df083aSStefano Zampini         if (need_benign_correction) {
4288df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4289a3df083aSStefano Zampini           PetscScalar        *marr;
4290a3df083aSStefano Zampini 
4291a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
429214393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
429314393ed6SStefano Zampini 
429414393ed6SStefano Zampini                  | 0 0  0 | (V)
429514393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
429614393ed6SStefano Zampini                  | 0 0 -1 | (p0)
429714393ed6SStefano Zampini 
429814393ed6SStefano Zampini           */
4299df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
430014393ed6SStefano Zampini             const PetscScalar *vals;
430114393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
430214393ed6SStefano Zampini             PetscInt          n,j,nz;
430314393ed6SStefano Zampini 
4304df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4305df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
430614393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
430714393ed6SStefano Zampini             for (j=0;j<n;j++) {
430814393ed6SStefano Zampini               PetscScalar val = vals[j];
430914393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
431014393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
431114393ed6SStefano Zampini             }
431214393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4313df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
431414393ed6SStefano Zampini           }
431572b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
431672b8c272SStefano Zampini         }
4317c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
4318c58f9fdbSStefano Zampini         Brhs = A_RV;
4319c58f9fdbSStefano Zampini       } else {
4320c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4321c58f9fdbSStefano Zampini 
4322c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4323fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
4324c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
4325c58f9fdbSStefano Zampini         } else {
4326c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
4327c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4328c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
4329c58f9fdbSStefano Zampini           A_RVT = A_VR;
4330c58f9fdbSStefano Zampini         }
4331c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4332c58f9fdbSStefano Zampini           PetscScalar *aa;
4333c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4334c58f9fdbSStefano Zampini           PetscBool   done;
4335c58f9fdbSStefano Zampini 
4336c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
433713903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4338c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4339c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4340c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
434113903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4342c58f9fdbSStefano Zampini         } else {
4343c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4344c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4345c58f9fdbSStefano Zampini         }
4346c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4347c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4348c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4349c58f9fdbSStefano Zampini       }
435072b8c272SStefano Zampini       if (F) {
435114393ed6SStefano Zampini         /* need to correct the rhs */
435272b8c272SStefano Zampini         if (need_benign_correction) {
435372b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
435472b8c272SStefano Zampini           PetscScalar        *marr;
435572b8c272SStefano Zampini 
4356c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
43575cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43585cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43595cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43605cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
43615cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43625cbda25cSStefano Zampini             }
43635cbda25cSStefano Zampini           } else {
4364a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4365a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43665cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4367a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4368a3df083aSStefano Zampini             }
43695cbda25cSStefano Zampini           }
4370c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4371a3df083aSStefano Zampini         }
4372c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4373c58f9fdbSStefano Zampini         if (restoreavr) {
4374c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4375c58f9fdbSStefano Zampini         }
437614393ed6SStefano Zampini         /* need to correct the solution */
4377a3df083aSStefano Zampini         if (need_benign_correction) {
4378df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4379a3df083aSStefano Zampini           PetscScalar        *marr;
4380a3df083aSStefano Zampini 
4381a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
43825cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43835cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43845cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
43855cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
43865cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
43875cbda25cSStefano Zampini             }
43885cbda25cSStefano Zampini           } else {
4389a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4390a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
43915cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4392a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4393a3df083aSStefano Zampini             }
43945cbda25cSStefano Zampini           }
4395a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4396a3df083aSStefano Zampini         }
439706656605SStefano Zampini       } else {
4398c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
439906656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4400ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4401ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
440206656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4403c0decd05SBarry Smith           ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
440406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
440506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
440606656605SStefano Zampini         }
4407c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
440806656605SStefano Zampini       }
440980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4410c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4411ffd830a3SStefano Zampini       /* S_VV and S_CV */
441206656605SStefano Zampini       if (n_constraints) {
441306656605SStefano Zampini         Mat B;
441480677318SStefano Zampini 
4415580bdb30SBarry Smith         ierr = PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices);CHKERRQ(ierr);
441680677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4417ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4418ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
441980677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442080677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
442180677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
442280677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
442380677318SStefano Zampini         }
4424ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
44254222ddf1SHong Zhang         /* Reuse dense S_C = pcbddc->local_auxmat1 * B */
44264222ddf1SHong Zhang         ierr = MatProductCreateWithMat(pcbddc->local_auxmat1,B,NULL,S_CV);CHKERRQ(ierr);
44274222ddf1SHong Zhang         ierr = MatProductSetType(S_CV,MATPRODUCT_AB);CHKERRQ(ierr);
44284222ddf1SHong Zhang         ierr = MatProductSetFromOptions(S_CV);CHKERRQ(ierr);
44296718818eSStefano Zampini         ierr = MatProductSymbolic(S_CV);CHKERRQ(ierr);
44304222ddf1SHong Zhang         ierr = MatProductNumeric(S_CV);CHKERRQ(ierr);
4431a961b312SStefano Zampini         ierr = MatProductClear(S_CV);CHKERRQ(ierr);
44324222ddf1SHong Zhang 
443380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4434ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
44354222ddf1SHong Zhang         /* Reuse B = local_auxmat2_R * S_CV */
44364222ddf1SHong Zhang         ierr = MatProductCreateWithMat(local_auxmat2_R,S_CV,NULL,B);CHKERRQ(ierr);
44374222ddf1SHong Zhang         ierr = MatProductSetType(B,MATPRODUCT_AB);CHKERRQ(ierr);
44384222ddf1SHong Zhang         ierr = MatProductSetFromOptions(B);CHKERRQ(ierr);
44396718818eSStefano Zampini         ierr = MatProductSymbolic(B);CHKERRQ(ierr);
44404222ddf1SHong Zhang         ierr = MatProductNumeric(B);CHKERRQ(ierr);
44414222ddf1SHong Zhang 
444206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4443ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4444ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
444506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
444606656605SStefano Zampini       }
4447ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4448ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4449ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4450ad16ce7aSStefano Zampini         ierr = MatDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4451ffd830a3SStefano Zampini       }
445206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
445314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
445414393ed6SStefano Zampini       if (need_benign_correction) {
4455df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
445614393ed6SStefano Zampini         PetscScalar        *marr,*sums;
445714393ed6SStefano Zampini 
445814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4459f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4460df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
446114393ed6SStefano Zampini           const PetscScalar *vals;
446214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
446314393ed6SStefano Zampini           PetscInt          n,j,nz;
446414393ed6SStefano Zampini 
4465df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4466df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
446714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
446814393ed6SStefano Zampini             PetscInt k;
446914393ed6SStefano Zampini             sums[j] = 0.;
447014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
447114393ed6SStefano Zampini           }
447214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
447314393ed6SStefano Zampini           for (j=0;j<n;j++) {
447414393ed6SStefano Zampini             PetscScalar val = vals[j];
447514393ed6SStefano Zampini             PetscInt k;
447614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
447714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
447814393ed6SStefano Zampini             }
447914393ed6SStefano Zampini           }
448014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4481df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
448214393ed6SStefano Zampini         }
448314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4484f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
448514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
448614393ed6SStefano Zampini       }
448780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
448806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
44891683a169SBarry Smith       ierr = MatDenseGetArrayRead(A_VV,&x);CHKERRQ(ierr);
449006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
449106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
44921683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(A_VV,&x);CHKERRQ(ierr);
449306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
449406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4495d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4496019a44ceSStefano Zampini     } else {
4497d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4498d16cbb6bSStefano Zampini     }
449921eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4500d16cbb6bSStefano Zampini 
450106656605SStefano Zampini     /* coarse basis functions */
450206656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
4503*ab2d12f3SJunchao Zhang       Vec         v;
4504*ab2d12f3SJunchao Zhang       PetscScalar one = 1.0,zero = 0.0;
450516f15bc4SStefano Zampini 
4506ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
4507*ab2d12f3SJunchao Zhang       ierr = MatDenseGetColumnVec(pcbddc->coarse_phi_B,i,&v);CHKERRQ(ierr);
4508*ab2d12f3SJunchao Zhang       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4509*ab2d12f3SJunchao Zhang       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4510*ab2d12f3SJunchao Zhang       if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4511*ab2d12f3SJunchao Zhang         PetscMPIInt rank;
4512*ab2d12f3SJunchao Zhang         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),&rank);CHKERRMPI(ierr);
4513*ab2d12f3SJunchao Zhang         if (rank > 1) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4514*ab2d12f3SJunchao Zhang       }
4515*ab2d12f3SJunchao Zhang       ierr = VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES);CHKERRQ(ierr);
4516*ab2d12f3SJunchao Zhang       ierr = VecAssemblyBegin(v);CHKERRQ(ierr); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */
4517*ab2d12f3SJunchao Zhang       ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
4518*ab2d12f3SJunchao Zhang       ierr = MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i,&v);CHKERRQ(ierr);
451906656605SStefano Zampini 
452006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45214f1b2e48SStefano Zampini         PetscInt j;
45224f1b2e48SStefano Zampini 
4523*ab2d12f3SJunchao Zhang         ierr = MatDenseGetColumnVec(pcbddc->coarse_phi_D,i,&v);CHKERRQ(ierr);
4524*ab2d12f3SJunchao Zhang         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4525*ab2d12f3SJunchao Zhang         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4526*ab2d12f3SJunchao Zhang         if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4527*ab2d12f3SJunchao Zhang           PetscMPIInt rank;
4528*ab2d12f3SJunchao Zhang           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),&rank);CHKERRMPI(ierr);
4529*ab2d12f3SJunchao Zhang           if (rank > 1) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4530*ab2d12f3SJunchao Zhang         }
4531*ab2d12f3SJunchao Zhang         for (j=0;j<pcbddc->benign_n;j++) {ierr = VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES);CHKERRQ(ierr);}
4532*ab2d12f3SJunchao Zhang         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
4533*ab2d12f3SJunchao Zhang         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
4534*ab2d12f3SJunchao Zhang         ierr = MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i,&v);CHKERRQ(ierr);
453506656605SStefano Zampini       }
453606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
453706656605SStefano Zampini     }
453804708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
453904708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
454006656605SStefano Zampini   }
45415cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
454206656605SStefano Zampini 
454306656605SStefano Zampini   if (n_constraints) {
454406656605SStefano Zampini     Mat B;
454506656605SStefano Zampini 
4546ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
454706656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
4548a961b312SStefano Zampini     ierr = MatProductCreateWithMat(local_auxmat2_R,S_CC,NULL,B);CHKERRQ(ierr);
4549a961b312SStefano Zampini     ierr = MatProductSetType(B,MATPRODUCT_AB);CHKERRQ(ierr);
4550a961b312SStefano Zampini     ierr = MatProductSetFromOptions(B);CHKERRQ(ierr);
45516718818eSStefano Zampini     ierr = MatProductSymbolic(B);CHKERRQ(ierr);
4552a961b312SStefano Zampini     ierr = MatProductNumeric(B);CHKERRQ(ierr);
4553a961b312SStefano Zampini 
455406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
455506656605SStefano Zampini     if (n_vertices) {
455603dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
455780677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
455880677318SStefano Zampini       } else {
455980677318SStefano Zampini         Mat S_VCt;
456080677318SStefano Zampini 
4561ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4562ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
456372b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4564ad16ce7aSStefano Zampini           ierr = MatDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4565ffd830a3SStefano Zampini         }
456680677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
456780677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
456880677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
456980677318SStefano Zampini       }
457006656605SStefano Zampini     }
457106656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
457206656605SStefano Zampini     /* coarse basis functions */
457306656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
4574*ab2d12f3SJunchao Zhang       Vec v;
457506656605SStefano Zampini 
4576ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
4577*ab2d12f3SJunchao Zhang       ierr = MatDenseGetColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v);CHKERRQ(ierr);
4578*ab2d12f3SJunchao Zhang       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4579*ab2d12f3SJunchao Zhang       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4580*ab2d12f3SJunchao Zhang       ierr = MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v);CHKERRQ(ierr);
458106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45824f1b2e48SStefano Zampini         PetscInt    j;
4583*ab2d12f3SJunchao Zhang         PetscScalar zero = 0.0;
4584*ab2d12f3SJunchao Zhang         ierr = MatDenseGetColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v);CHKERRQ(ierr);
4585*ab2d12f3SJunchao Zhang         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4586*ab2d12f3SJunchao Zhang         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4587*ab2d12f3SJunchao Zhang         for (j=0;j<pcbddc->benign_n;j++) {ierr = VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES);CHKERRQ(ierr);}
4588*ab2d12f3SJunchao Zhang         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
4589*ab2d12f3SJunchao Zhang         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
4590*ab2d12f3SJunchao Zhang         ierr = MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v);CHKERRQ(ierr);
459106656605SStefano Zampini       }
459206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
459306656605SStefano Zampini     }
459406656605SStefano Zampini   }
459580677318SStefano Zampini   if (n_constraints) {
459680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
459780677318SStefano Zampini   }
45984f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
459972b8c272SStefano Zampini 
460072b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
460172b8c272SStefano Zampini   if (pcbddc->benign_n) {
460272b8c272SStefano Zampini     Mat               B0_B,B0_BPHI;
460372b8c272SStefano Zampini     IS                is_dummy;
46041683a169SBarry Smith     const PetscScalar *data;
460572b8c272SStefano Zampini     PetscInt          j;
460672b8c272SStefano Zampini 
460772b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
46087dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
460972b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
461072b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
461186c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
46121683a169SBarry Smith     ierr = MatDenseGetArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
461372b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
461472b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
461572b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
461672b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
461772b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
461872b8c272SStefano Zampini       }
461972b8c272SStefano Zampini     }
46201683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(B0_BPHI,&data);CHKERRQ(ierr);
462172b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
462272b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
462372b8c272SStefano Zampini   }
4624019a44ceSStefano Zampini 
462506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
46263301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4627ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4628ffd830a3SStefano Zampini     PetscScalar *marray;
462906656605SStefano Zampini 
463006656605SStefano Zampini     if (n_constraints) {
4631ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
463206656605SStefano Zampini 
4633abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
463406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4635ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
463616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
463706656605SStefano Zampini       if (n_vertices) {
4638ffd830a3SStefano Zampini         Mat S_VCT;
463906656605SStefano Zampini 
464006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4641ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
464216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
464306656605SStefano Zampini       }
4644ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
46455b782168SStefano Zampini     } else {
46465b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
464706656605SStefano Zampini     }
464816f15bc4SStefano Zampini     if (n_vertices && n_R) {
4649ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4650ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4651ffd830a3SStefano Zampini       PetscInt       n;
4652ffd830a3SStefano Zampini       PetscBool      flg_row;
465306656605SStefano Zampini 
4654ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4655af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4656ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4657ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4658ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4659ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4660ffd830a3SStefano Zampini         PetscInt j;
4661ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4662ffd830a3SStefano Zampini       }
4663ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4664ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4665ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
466606656605SStefano Zampini     }
466706656605SStefano Zampini 
4668ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4669abc8f43dSstefano_zampini     if (n_vertices) {
4670ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4671ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4672ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4673ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
467406656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4675c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
467606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
467706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
467806656605SStefano Zampini       }
4679ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4680abc8f43dSstefano_zampini     }
46815b782168SStefano Zampini     if (B_C) {
4682ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4683ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4684ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4685ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4686ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4687c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
4688ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4689ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
469006656605SStefano Zampini       }
4691ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
46925b782168SStefano Zampini     }
469306656605SStefano Zampini     /* coarse basis functions */
469406656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4695*ab2d12f3SJunchao Zhang       Vec  v;
469606656605SStefano Zampini 
4697ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
4698*ab2d12f3SJunchao Zhang       ierr = MatDenseGetColumnVec(pcbddc->coarse_psi_B,i,&v);CHKERRQ(ierr);
4699*ab2d12f3SJunchao Zhang       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4700*ab2d12f3SJunchao Zhang       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
470106656605SStefano Zampini       if (i<n_vertices) {
4702*ab2d12f3SJunchao Zhang         PetscScalar one = 1.0;
4703*ab2d12f3SJunchao Zhang         ierr = VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES);CHKERRQ(ierr);
4704*ab2d12f3SJunchao Zhang         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
4705*ab2d12f3SJunchao Zhang         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
470606656605SStefano Zampini       }
4707*ab2d12f3SJunchao Zhang       ierr = MatDenseRestoreColumnVec(pcbddc->coarse_psi_B,i,&v);CHKERRQ(ierr);
470806656605SStefano Zampini 
470906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
4710*ab2d12f3SJunchao Zhang         ierr = MatDenseGetColumnVec(pcbddc->coarse_psi_D,i,&v);CHKERRQ(ierr);
4711*ab2d12f3SJunchao Zhang         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4712*ab2d12f3SJunchao Zhang         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4713*ab2d12f3SJunchao Zhang         ierr = MatDenseRestoreColumnVec(pcbddc->coarse_psi_D,i,&v);CHKERRQ(ierr);
471406656605SStefano Zampini       }
471506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
471606656605SStefano Zampini     }
4717ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4718ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
471906656605SStefano Zampini   }
4720a6e023c1Sstefano_zampini 
4721d62866d3SStefano Zampini   /* free memory */
472288ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
472306656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
472406656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
472506656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
472606656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4727d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4728d62866d3SStefano Zampini   if (n_vertices) {
4729d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4730d62866d3SStefano Zampini   }
4731d62866d3SStefano Zampini   if (n_constraints) {
4732d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4733d62866d3SStefano Zampini   }
47348ead10e4SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
47358ead10e4SStefano Zampini 
473688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
473788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
473888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4739d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
474088ebb749SStefano Zampini     Mat         coarse_sub_mat;
474125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
474288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
474388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
474488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
47458bec7fa6SStefano Zampini     Mat         C_B,CPHI;
47468bec7fa6SStefano Zampini     IS          is_dummy;
47478bec7fa6SStefano Zampini     Vec         mones;
474888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
474988ebb749SStefano Zampini     PetscReal   real_value;
475088ebb749SStefano Zampini 
4751a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4752a3df083aSStefano Zampini       Mat A;
4753a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
47547dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
47557dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
47567dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
47577dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4758a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4759a3df083aSStefano Zampini     } else {
476088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
476188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
476288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
476388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4764a3df083aSStefano Zampini     }
476588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
476688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4767ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
476888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
476988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
477088ebb749SStefano Zampini     }
477188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
477288ebb749SStefano Zampini 
477325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47743301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
477525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4776ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
477788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
477888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
477988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
478088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
478188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
478288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
478388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
478488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
478588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
478688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
478788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
478888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
478988ebb749SStefano Zampini     } else {
479088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
479188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
479288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
479388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
479488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
479588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
479688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
479788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
479888ebb749SStefano Zampini     }
479988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
480088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
480188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4802511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
48034f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4804fc227af8SStefano Zampini       Mat               B0_B,B0_BPHI;
48051683a169SBarry Smith       const PetscScalar *data2;
48061683a169SBarry Smith       PetscScalar       *data;
48074f1b2e48SStefano Zampini       PetscInt          j;
4808d12edf2fSStefano Zampini 
48094f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
48107dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4811d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
481286c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4813d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
48141683a169SBarry Smith       ierr = MatDenseGetArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
48154f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
48164f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4817d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
48184f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
48194f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
48204f1b2e48SStefano Zampini         }
4821d12edf2fSStefano Zampini       }
4822d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
48231683a169SBarry Smith       ierr = MatDenseRestoreArrayRead(B0_BPHI,&data2);CHKERRQ(ierr);
4824d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4825d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4826d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4827d12edf2fSStefano Zampini     }
4828d12edf2fSStefano Zampini #if 0
4829d12edf2fSStefano Zampini   {
4830d12edf2fSStefano Zampini     PetscViewer viewer;
4831d12edf2fSStefano Zampini     char filename[256];
4832ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4833d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4834a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4835ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4836ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4837ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4838d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4839a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4840ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4841ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
484272b8c272SStefano Zampini     }
4843ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4844ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4845ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4846ffd830a3SStefano Zampini     }
4847ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4848ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4849ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4850ffd830a3SStefano Zampini     }
485172b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4852ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4853ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4854ffd830a3SStefano Zampini     }
4855fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->local_mat,"A");CHKERRQ(ierr);
4856fb6280fbSStefano Zampini     ierr = MatView(pcbddc->local_mat,viewer);CHKERRQ(ierr);
4857fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C");CHKERRQ(ierr);
4858fb6280fbSStefano Zampini     ierr = MatView(pcbddc->ConstraintMatrix,viewer);CHKERRQ(ierr);
4859fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_I_local,"I");CHKERRQ(ierr);
4860fb6280fbSStefano Zampini     ierr = ISView(pcis->is_I_local,viewer);CHKERRQ(ierr);
4861fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcis->is_B_local,"B");CHKERRQ(ierr);
4862fb6280fbSStefano Zampini     ierr = ISView(pcis->is_B_local,viewer);CHKERRQ(ierr);
4863fb6280fbSStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R");CHKERRQ(ierr);
4864fb6280fbSStefano Zampini     ierr = ISView(pcbddc->is_R_local,viewer);CHKERRQ(ierr);
4865d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4866d12edf2fSStefano Zampini   }
4867d12edf2fSStefano Zampini #endif
486881d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
48698bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
48701575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
487106656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
48728bec7fa6SStefano Zampini 
48738bec7fa6SStefano Zampini     /* check constraints */
4874a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
48757dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
48764f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
48778bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4878a00504b5SStefano Zampini     } else {
4879a00504b5SStefano Zampini       PetscScalar *data;
4880a00504b5SStefano Zampini       Mat         tmat;
4881a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4882a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4883a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4884a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4885a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4886a00504b5SStefano Zampini     }
48878bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
48888bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
48898bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
48908bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4891bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4892ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4893bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4894bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4895bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4896bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4897bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
489888ebb749SStefano Zampini     }
48998bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
49008bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
49018bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
49028bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
490325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
490488ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
490588ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
490688ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
490788ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
490888ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
490988ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
491088ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
491188ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
491288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
491388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4914ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
491588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
491688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
491788ebb749SStefano Zampini     }
491888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
491988ebb749SStefano Zampini   }
49207ebab0bbSStefano Zampini   /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */
49217ebab0bbSStefano Zampini   {
49227ebab0bbSStefano Zampini     PetscBool gpu;
49237ebab0bbSStefano Zampini 
49247ebab0bbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcis->vec1_N,VECSEQCUDA,&gpu);CHKERRQ(ierr);
49257ebab0bbSStefano Zampini     if (gpu) {
49267ebab0bbSStefano Zampini       if (pcbddc->local_auxmat1) {
49277ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->local_auxmat1,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat1);CHKERRQ(ierr);
49287ebab0bbSStefano Zampini       }
49297ebab0bbSStefano Zampini       if (pcbddc->local_auxmat2) {
49307ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->local_auxmat2,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
49317ebab0bbSStefano Zampini       }
49327ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_B) {
49337ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_phi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
49347ebab0bbSStefano Zampini       }
49357ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_D) {
49367ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_phi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
49377ebab0bbSStefano Zampini       }
49387ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_B) {
49397ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
49407ebab0bbSStefano Zampini       }
49417ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_D) {
49427ebab0bbSStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
49437ebab0bbSStefano Zampini       }
49447ebab0bbSStefano Zampini     }
49457ebab0bbSStefano Zampini   }
49468629588bSStefano Zampini   /* get back data */
49478629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
494888ebb749SStefano Zampini   PetscFunctionReturn(0);
494988ebb749SStefano Zampini }
495088ebb749SStefano Zampini 
49517dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4952aa0d41d4SStefano Zampini {
4953d65f70fdSStefano Zampini   Mat            *work_mat;
4954d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4955d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4956c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4957aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4958aa0d41d4SStefano Zampini 
4959aa0d41d4SStefano Zampini   PetscFunctionBegin;
4960d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4961d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4962d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4963d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4964aa0d41d4SStefano Zampini 
4965d65f70fdSStefano Zampini   if (!rsorted) {
4966906d46d4SStefano Zampini     const PetscInt *idxs;
4967906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4968aa0d41d4SStefano Zampini 
4969d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4970d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4971d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4972d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4973aa0d41d4SStefano Zampini     }
4974d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4975d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4976d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4977d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4978aa0d41d4SStefano Zampini     }
4979d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4980d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4981d65f70fdSStefano Zampini   } else {
4982d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4983d65f70fdSStefano Zampini     isrow_s = isrow;
4984aa0d41d4SStefano Zampini   }
4985906d46d4SStefano Zampini 
4986d65f70fdSStefano Zampini   if (!csorted) {
4987d65f70fdSStefano Zampini     if (isrow == iscol) {
4988d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4989d65f70fdSStefano Zampini       iscol_s = isrow_s;
4990d65f70fdSStefano Zampini     } else {
4991d65f70fdSStefano Zampini       const PetscInt *idxs;
4992d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4993906d46d4SStefano Zampini 
4994d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4995d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4996d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4997d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4998d65f70fdSStefano Zampini       }
4999d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
5000d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
5001d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
5002d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
5003d65f70fdSStefano Zampini       }
5004d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
5005d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
5006d65f70fdSStefano Zampini     }
5007d65f70fdSStefano Zampini   } else {
5008d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
5009d65f70fdSStefano Zampini     iscol_s = iscol;
5010d65f70fdSStefano Zampini   }
5011d65f70fdSStefano Zampini 
50127dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5013d65f70fdSStefano Zampini 
5014d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
5015906d46d4SStefano Zampini     Mat      new_mat;
5016d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
5017906d46d4SStefano Zampini 
5018d65f70fdSStefano Zampini     if (!rsorted) {
5019d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
5020d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
5021d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
5022d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
5023906d46d4SStefano Zampini       }
5024d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
5025d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
5026d65f70fdSStefano Zampini     } else {
5027d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
5028906d46d4SStefano Zampini     }
5029d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
5030d65f70fdSStefano Zampini 
5031d65f70fdSStefano Zampini     if (!csorted) {
5032d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
5033d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
5034d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
5035d65f70fdSStefano Zampini       } else {
5036d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
5037f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
5038d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
5039d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
5040d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
5041d65f70fdSStefano Zampini         }
5042d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
5043d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
5044d65f70fdSStefano Zampini       }
5045d65f70fdSStefano Zampini     } else {
5046d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
5047d65f70fdSStefano Zampini     }
5048d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
5049d65f70fdSStefano Zampini 
5050d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
5051d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
5052d65f70fdSStefano Zampini     work_mat[0] = new_mat;
5053d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
5054d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
5055d65f70fdSStefano Zampini   }
5056d65f70fdSStefano Zampini 
5057d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
5058d65f70fdSStefano Zampini   *B = work_mat[0];
5059d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
5060d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
5061d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
5062d65f70fdSStefano Zampini   PetscFunctionReturn(0);
5063d65f70fdSStefano Zampini }
5064d65f70fdSStefano Zampini 
50655e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
5066aa0d41d4SStefano Zampini {
5067aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
50685e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5069022d8d2bSstefano_zampini   Mat            new_mat,lA;
50705e8657edSStefano Zampini   IS             is_local,is_global;
5071d65f70fdSStefano Zampini   PetscInt       local_size;
5072d65f70fdSStefano Zampini   PetscBool      isseqaij;
5073aa0d41d4SStefano Zampini   PetscErrorCode ierr;
5074aa0d41d4SStefano Zampini 
5075aa0d41d4SStefano Zampini   PetscFunctionBegin;
5076aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
50775e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
50785e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
5079b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
5080aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
50817dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
5082aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
5083906d46d4SStefano Zampini 
5084906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
5085906d46d4SStefano Zampini     Vec       x,x_change;
5086906d46d4SStefano Zampini     PetscReal error;
5087906d46d4SStefano Zampini 
50885e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
5089906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
50905e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
5091e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5092e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5093d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
509488428137SStefano Zampini     if (!pcbddc->change_interior) {
509588428137SStefano Zampini       const PetscScalar *x,*y,*v;
509688428137SStefano Zampini       PetscReal         lerror = 0.;
509788428137SStefano Zampini       PetscInt          i;
509888428137SStefano Zampini 
509988428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
510088428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
510188428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
510288428137SStefano Zampini       for (i=0;i<local_size;i++)
510388428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
510488428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
510588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
510688428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
510788428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
5108820f2d46SBarry Smith       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
5109637e8532SStefano Zampini       if (error > PETSC_SMALL) {
5110637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
51116080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",error);
5112637e8532SStefano Zampini         } else {
51136080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",error);
5114637e8532SStefano Zampini         }
5115637e8532SStefano Zampini       }
511688428137SStefano Zampini     }
5117e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5118e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5119906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5120906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5121637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5122637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
51236080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
5124637e8532SStefano Zampini       } else {
51256080607fSStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",error);
5126637e8532SStefano Zampini       }
5127637e8532SStefano Zampini     }
5128906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
5129906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5130906d46d4SStefano Zampini   }
5131906d46d4SStefano Zampini 
5132022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
5133022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
5134022d8d2bSstefano_zampini 
513522d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
51367ebab0bbSStefano Zampini   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
513722d5777bSStefano Zampini   if (isseqaij) {
5138a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5139a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
5140022d8d2bSstefano_zampini     if (lA) {
5141022d8d2bSstefano_zampini       Mat work;
5142022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5143022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5144022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5145022d8d2bSstefano_zampini     }
5146aa0d41d4SStefano Zampini   } else {
5147a00504b5SStefano Zampini     Mat work_mat;
51481cf9b237SStefano Zampini 
5149a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5150aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5151a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
51521d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
5153022d8d2bSstefano_zampini     if (lA) {
5154022d8d2bSstefano_zampini       Mat work;
5155022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
5156022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
5157022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
5158022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
5159022d8d2bSstefano_zampini     }
5160aa0d41d4SStefano Zampini   }
51613301b35fSStefano Zampini   if (matis->A->symmetric_set) {
51623301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
5163e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
51643301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
5165e496cd5dSStefano Zampini #endif
51663301b35fSStefano Zampini   }
5167d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
5168aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
5169aa0d41d4SStefano Zampini }
5170aa0d41d4SStefano Zampini 
51718ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
5172a64d13efSStefano Zampini {
5173a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
5174a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5175d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
517653892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
51773a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
51783a50541eSStefano Zampini   PetscInt        vbs,bs;
51796816873aSStefano Zampini   PetscBT         bitmask=NULL;
5180a64d13efSStefano Zampini   PetscErrorCode  ierr;
5181a64d13efSStefano Zampini 
5182a64d13efSStefano Zampini   PetscFunctionBegin;
5183b23d619eSStefano Zampini   /*
5184b23d619eSStefano Zampini     No need to setup local scatters if
5185b23d619eSStefano Zampini       - primal space is unchanged
5186b23d619eSStefano Zampini         AND
5187b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
5188b23d619eSStefano Zampini         AND
5189b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5190b23d619eSStefano Zampini   */
5191b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5192f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5193f4ddd8eeSStefano Zampini   }
5194f4ddd8eeSStefano Zampini   /* destroy old objects */
5195f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
5196f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
5197f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
5198a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5199b371cd4fSStefano Zampini   n_B = pcis->n_B;
5200b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5201b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
52023a50541eSStefano Zampini 
5203a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
52046816873aSStefano Zampini 
520553892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5206b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
5207854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
5208a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
5209a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
52100e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
5211a64d13efSStefano Zampini     }
5212a64d13efSStefano Zampini 
5213a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
52144641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
52156816873aSStefano Zampini         idx_R_local[n_R++] = i;
5216a64d13efSStefano Zampini       }
5217a64d13efSStefano Zampini     }
5218df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5219df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
52206816873aSStefano Zampini 
5221df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5222df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
52236816873aSStefano Zampini   }
52243a50541eSStefano Zampini 
52253a50541eSStefano Zampini   /* Block code */
52263a50541eSStefano Zampini   vbs = 1;
52273a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
52283a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
52293a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
52303a50541eSStefano Zampini     PetscInt  *vary;
5231b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
5232785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
5233580bdb30SBarry Smith       ierr = PetscArrayzero(vary,pcis->n/bs);CHKERRQ(ierr);
5234d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5235d3df7717SStefano 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 */
52360e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5237d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
52383a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
52393a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
52403a50541eSStefano Zampini           break;
52413a50541eSStefano Zampini         }
52423a50541eSStefano Zampini       }
5243d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
5244d3df7717SStefano Zampini     } else {
5245d3df7717SStefano Zampini       /* Verify directly the R set */
5246d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5247d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5248d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5249d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5250d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5251d3df7717SStefano Zampini             break;
5252d3df7717SStefano Zampini           }
5253d3df7717SStefano Zampini         }
5254d3df7717SStefano Zampini       }
5255d3df7717SStefano Zampini     }
52563a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
52573a50541eSStefano Zampini       vbs = bs;
52583a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
52593a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
52603a50541eSStefano Zampini       }
52613a50541eSStefano Zampini     }
52623a50541eSStefano Zampini   }
52633a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
5264b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5265df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
526653892102SStefano Zampini 
5267df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5268df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
526953892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
5270df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
527153892102SStefano Zampini   } else {
52723a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
527353892102SStefano Zampini   }
5274a64d13efSStefano Zampini 
5275a64d13efSStefano Zampini   /* print some info if requested */
5276a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
5277a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5278a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
52791575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5280a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
52816080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %D, dirichlet_size = %D, boundary_size = %D\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
52826080607fSStefano 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);
5283a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5284a64d13efSStefano Zampini   }
5285a64d13efSStefano Zampini 
5286a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5287b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
52886816873aSStefano Zampini     IS       is_aux1,is_aux2;
52896816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
52906816873aSStefano Zampini 
52913a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5292854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
5293854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
5294a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
52954641a718SStefano Zampini     for (i=0; i<n_D; i++) {
52964641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
52974641a718SStefano Zampini     }
5298a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5299a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
53004641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
53014641a718SStefano Zampini         aux_array1[j++] = i;
5302a64d13efSStefano Zampini       }
5303a64d13efSStefano Zampini     }
5304a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
5305a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5306a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
53074641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
53084641a718SStefano Zampini         aux_array2[j++] = i;
5309a64d13efSStefano Zampini       }
5310a64d13efSStefano Zampini     }
5311a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5312a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
53139448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
5314a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5315a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
5316a64d13efSStefano Zampini 
53178eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
5318785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
5319a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
53204641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
53214641a718SStefano Zampini           aux_array1[j++] = i;
5322a64d13efSStefano Zampini         }
5323a64d13efSStefano Zampini       }
5324a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
53259448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
5326a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
5327a64d13efSStefano Zampini     }
53284641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
53293a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
5330d62866d3SStefano Zampini   } else {
5331df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
53326816873aSStefano Zampini     IS                 tis;
53336816873aSStefano Zampini     PetscInt           schur_size;
53346816873aSStefano Zampini 
5335df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
53366816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
53379448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
53386816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
53396816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
53406816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
53419448b7f1SJunchao Zhang       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
53426816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
5343d62866d3SStefano Zampini     }
5344d62866d3SStefano Zampini   }
5345a64d13efSStefano Zampini   PetscFunctionReturn(0);
5346a64d13efSStefano Zampini }
5347a64d13efSStefano Zampini 
53486d9e27e4SStefano Zampini static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B)
534992cccca0SStefano Zampini {
535092cccca0SStefano Zampini   MatNullSpace   NullSpace;
535192cccca0SStefano Zampini   Mat            dmat;
535292cccca0SStefano Zampini   const Vec      *nullvecs;
535392cccca0SStefano Zampini   Vec            v,v2,*nullvecs2;
53546d9e27e4SStefano Zampini   VecScatter     sct = NULL;
5355eb06acf8SStefano Zampini   PetscContainer c;
5356eb06acf8SStefano Zampini   PetscScalar    *ddata;
5357295df10fSStefano Zampini   PetscInt       k,nnsp_size,bsiz,bsiz2,n,N,bs;
535892cccca0SStefano Zampini   PetscBool      nnsp_has_cnst;
535992cccca0SStefano Zampini   PetscErrorCode ierr;
536092cccca0SStefano Zampini 
536192cccca0SStefano Zampini   PetscFunctionBegin;
53626d9e27e4SStefano Zampini   if (!is && !B) { /* MATIS */
53636d9e27e4SStefano Zampini     Mat_IS* matis = (Mat_IS*)A->data;
53646d9e27e4SStefano Zampini 
53656d9e27e4SStefano Zampini     if (!B) {
53666d9e27e4SStefano Zampini       ierr = MatISGetLocalMat(A,&B);CHKERRQ(ierr);
53676d9e27e4SStefano Zampini     }
53686d9e27e4SStefano Zampini     sct  = matis->cctx;
53696d9e27e4SStefano Zampini     ierr = PetscObjectReference((PetscObject)sct);CHKERRQ(ierr);
53706d9e27e4SStefano Zampini   } else {
537192cccca0SStefano Zampini     ierr = MatGetNullSpace(B,&NullSpace);CHKERRQ(ierr);
537292cccca0SStefano Zampini     if (!NullSpace) {
537392cccca0SStefano Zampini       ierr = MatGetNearNullSpace(B,&NullSpace);CHKERRQ(ierr);
537492cccca0SStefano Zampini     }
537592cccca0SStefano Zampini     if (NullSpace) PetscFunctionReturn(0);
53766d9e27e4SStefano Zampini   }
537792cccca0SStefano Zampini   ierr = MatGetNullSpace(A,&NullSpace);CHKERRQ(ierr);
537892cccca0SStefano Zampini   if (!NullSpace) {
537992cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A,&NullSpace);CHKERRQ(ierr);
538092cccca0SStefano Zampini   }
538192cccca0SStefano Zampini   if (!NullSpace) PetscFunctionReturn(0);
53826d9e27e4SStefano Zampini 
538392cccca0SStefano Zampini   ierr = MatCreateVecs(A,&v,NULL);CHKERRQ(ierr);
538492cccca0SStefano Zampini   ierr = MatCreateVecs(B,&v2,NULL);CHKERRQ(ierr);
53856d9e27e4SStefano Zampini   if (!sct) {
53869448b7f1SJunchao Zhang     ierr = VecScatterCreate(v,is,v2,NULL,&sct);CHKERRQ(ierr);
53876d9e27e4SStefano Zampini   }
538892cccca0SStefano Zampini   ierr = MatNullSpaceGetVecs(NullSpace,&nnsp_has_cnst,&nnsp_size,(const Vec**)&nullvecs);CHKERRQ(ierr);
5389295df10fSStefano Zampini   bsiz = bsiz2 = nnsp_size+!!nnsp_has_cnst;
539092cccca0SStefano Zampini   ierr = PetscMalloc1(bsiz,&nullvecs2);CHKERRQ(ierr);
539192cccca0SStefano Zampini   ierr = VecGetBlockSize(v2,&bs);CHKERRQ(ierr);
539292cccca0SStefano Zampini   ierr = VecGetSize(v2,&N);CHKERRQ(ierr);
539392cccca0SStefano Zampini   ierr = VecGetLocalSize(v2,&n);CHKERRQ(ierr);
5394eb06acf8SStefano Zampini   ierr = PetscMalloc1(n*bsiz,&ddata);CHKERRQ(ierr);
539592cccca0SStefano Zampini   for (k=0;k<nnsp_size;k++) {
5396eb06acf8SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*k,&nullvecs2[k]);CHKERRQ(ierr);
539792cccca0SStefano Zampini     ierr = VecScatterBegin(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
539892cccca0SStefano Zampini     ierr = VecScatterEnd(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
539992cccca0SStefano Zampini   }
540092cccca0SStefano Zampini   if (nnsp_has_cnst) {
5401eb06acf8SStefano Zampini     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*nnsp_size,&nullvecs2[nnsp_size]);CHKERRQ(ierr);
540292cccca0SStefano Zampini     ierr = VecSet(nullvecs2[nnsp_size],1.0);CHKERRQ(ierr);
540392cccca0SStefano Zampini   }
5404295df10fSStefano Zampini   ierr = PCBDDCOrthonormalizeVecs(&bsiz2,nullvecs2);CHKERRQ(ierr);
5405295df10fSStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)B),PETSC_FALSE,bsiz2,nullvecs2,&NullSpace);CHKERRQ(ierr);
5406295df10fSStefano Zampini 
5407eb06acf8SStefano Zampini   ierr = MatCreateDense(PetscObjectComm((PetscObject)B),n,PETSC_DECIDE,N,bsiz2,ddata,&dmat);CHKERRQ(ierr);
5408eb06acf8SStefano Zampini   ierr = PetscContainerCreate(PetscObjectComm((PetscObject)B),&c);CHKERRQ(ierr);
5409eb06acf8SStefano Zampini   ierr = PetscContainerSetPointer(c,ddata);CHKERRQ(ierr);
5410eb06acf8SStefano Zampini   ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
5411eb06acf8SStefano Zampini   ierr = PetscObjectCompose((PetscObject)dmat,"_PBDDC_Null_dmat_arr",(PetscObject)c);CHKERRQ(ierr);
5412eb06acf8SStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
541392cccca0SStefano Zampini   ierr = PetscObjectCompose((PetscObject)NullSpace,"_PBDDC_Null_dmat",(PetscObject)dmat);CHKERRQ(ierr);
541492cccca0SStefano Zampini   ierr = MatDestroy(&dmat);CHKERRQ(ierr);
5415eb06acf8SStefano Zampini 
541692cccca0SStefano Zampini   for (k=0;k<bsiz;k++) {
541792cccca0SStefano Zampini     ierr = VecDestroy(&nullvecs2[k]);CHKERRQ(ierr);
541892cccca0SStefano Zampini   }
541992cccca0SStefano Zampini   ierr = PetscFree(nullvecs2);CHKERRQ(ierr);
542092cccca0SStefano Zampini   ierr = MatSetNearNullSpace(B,NullSpace);CHKERRQ(ierr);
542192cccca0SStefano Zampini   ierr = MatNullSpaceDestroy(&NullSpace);CHKERRQ(ierr);
542292cccca0SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
542392cccca0SStefano Zampini   ierr = VecDestroy(&v2);CHKERRQ(ierr);
542492cccca0SStefano Zampini   ierr = VecScatterDestroy(&sct);CHKERRQ(ierr);
542592cccca0SStefano Zampini   PetscFunctionReturn(0);
542692cccca0SStefano Zampini }
5427304d26faSStefano Zampini 
5428684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5429304d26faSStefano Zampini {
5430304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5431304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5432304d26faSStefano Zampini   PC             pc_temp;
5433304d26faSStefano Zampini   Mat            A_RR;
543492cccca0SStefano Zampini   MatNullSpace   nnsp;
5435f4ddd8eeSStefano Zampini   MatReuse       reuse;
5436304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5437304d26faSStefano Zampini   PetscReal      value;
543804708bb6SStefano Zampini   PetscInt       n_D,n_R;
543992cccca0SStefano Zampini   PetscBool      issbaij,opts;
5440304d26faSStefano Zampini   PetscErrorCode ierr;
54410a545947SLisandro Dalcin   void           (*f)(void) = NULL;
5442312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5443e604994aSStefano Zampini   size_t         len;
5444304d26faSStefano Zampini 
5445304d26faSStefano Zampini   PetscFunctionBegin;
544643371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
54476d9e27e4SStefano Zampini   /* approximate solver, propagate NearNullSpace if needed */
54486d9e27e4SStefano Zampini   if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) {
54496d9e27e4SStefano Zampini     MatNullSpace gnnsp1,gnnsp2;
54506d9e27e4SStefano Zampini     PetscBool    lhas,ghas;
54516d9e27e4SStefano Zampini 
54526d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pcbddc->local_mat,&nnsp);CHKERRQ(ierr);
54536d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&gnnsp1);CHKERRQ(ierr);
54546d9e27e4SStefano Zampini     ierr = MatGetNullSpace(pc->pmat,&gnnsp2);CHKERRQ(ierr);
54556d9e27e4SStefano Zampini     lhas = nnsp ? PETSC_TRUE : PETSC_FALSE;
5456820f2d46SBarry Smith     ierr = MPIU_Allreduce(&lhas,&ghas,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
54576d9e27e4SStefano Zampini     if (!ghas && (gnnsp1 || gnnsp2)) {
54586d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pc->pmat,NULL,NULL);CHKERRQ(ierr);
54596d9e27e4SStefano Zampini     }
54606d9e27e4SStefano Zampini   }
54616d9e27e4SStefano Zampini 
5462e604994aSStefano Zampini   /* compute prefixes */
5463e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
5464e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
5465e604994aSStefano Zampini   if (!pcbddc->current_level) {
5466a126751eSBarry Smith     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix));CHKERRQ(ierr);
5467a126751eSBarry Smith     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix));CHKERRQ(ierr);
5468a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5469a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5470e604994aSStefano Zampini   } else {
547135529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
5472e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5473e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5474312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5475312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5476a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
547734d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
547834d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5479a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix));CHKERRQ(ierr);
5480a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix));CHKERRQ(ierr);
5481a126751eSBarry Smith     ierr = PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix));CHKERRQ(ierr);
5482a126751eSBarry Smith     ierr = PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix));CHKERRQ(ierr);
5483e604994aSStefano Zampini   }
5484e604994aSStefano Zampini 
5485304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5486684f6988SStefano Zampini   if (dirichlet) {
5487d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5488450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
54896080607fSStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
5490450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5491a3df083aSStefano Zampini         Mat    A_IIn;
5492a3df083aSStefano Zampini 
5493a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
5494a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
5495a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5496a3df083aSStefano Zampini       }
5497450f8f5eSStefano Zampini     }
54983301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5499d1e098c7SStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
5500964fefecSStefano Zampini     }
5501ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5502964fefecSStefano Zampini     n_D  = pcis->n - pcis->n_B;
550392cccca0SStefano Zampini     opts = PETSC_FALSE;
5504304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
550592cccca0SStefano Zampini       opts = PETSC_TRUE;
5506304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5507304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5508304d26faSStefano Zampini       /* default */
5509304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5510e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
55112f37b69bSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->pA_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5512304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
55139577ea80SStefano Zampini       if (issbaij) {
55149577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
55159577ea80SStefano Zampini       } else {
5516304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
55179577ea80SStefano Zampini       }
5518399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure);CHKERRQ(ierr);
551992cccca0SStefano Zampini     }
552092cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(pcis->pA_II,((PetscObject)pcbddc->ksp_D)->prefix);CHKERRQ(ierr);
55212f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->pA_II);CHKERRQ(ierr);
5522304d26faSStefano Zampini     /* Allow user's customization */
552392cccca0SStefano Zampini     if (opts) {
5524304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
552592cccca0SStefano Zampini     }
55266d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(pcis->pA_II,&nnsp);CHKERRQ(ierr);
55276d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */
55286d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II);CHKERRQ(ierr);
552992cccca0SStefano Zampini     }
553092cccca0SStefano Zampini     ierr = MatGetNearNullSpace(pcis->pA_II,&nnsp);CHKERRQ(ierr);
553192cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5532cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
553392cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5534cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5535cd18cfedSStefano Zampini       const PetscInt *idxs;
5536cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5537cd18cfedSStefano Zampini 
5538cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcis->is_I_local,&nl);CHKERRQ(ierr);
5539cd18cfedSStefano Zampini       ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5540cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5541cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5542cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5543cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5544cd18cfedSStefano Zampini         }
5545cd18cfedSStefano Zampini       }
5546cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
5547cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5548cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5549cd18cfedSStefano Zampini     }
5550b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5551df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5552d62866d3SStefano Zampini 
5553df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5554d5574798SStefano Zampini     }
555592cccca0SStefano Zampini 
5556304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5557304d26faSStefano Zampini     if (!n_D) {
5558304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5559304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5560304d26faSStefano Zampini     }
556193120301SStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
5562304d26faSStefano Zampini     /* set ksp_D into pcis data */
5563304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
556492cccca0SStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5565304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5566684f6988SStefano Zampini   }
5567304d26faSStefano Zampini 
5568304d26faSStefano Zampini   /* NEUMANN PROBLEM */
55690a545947SLisandro Dalcin   A_RR = NULL;
5570684f6988SStefano Zampini   if (neumann) {
5571d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
557204708bb6SStefano Zampini     PetscInt        ibs,mbs;
55730aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
557404708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
55750aa714b2SStefano Zampini 
55760aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
55770aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
55780aa714b2SStefano Zampini       IS iP;
55790aa714b2SStefano Zampini 
55800aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
55810aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
55820aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
55830aa714b2SStefano Zampini     }
5584f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
55858ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5586f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5587f4ddd8eeSStefano Zampini       PetscInt nn_R;
558881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5589f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5590f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5591f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5592f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5593f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5594f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5595f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5596727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5597f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5598f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5599f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5600f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5601f4ddd8eeSStefano Zampini         }
5602f4ddd8eeSStefano Zampini       }
5603f4ddd8eeSStefano Zampini       /* last check */
5604d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5605f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5606f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5607f4ddd8eeSStefano Zampini       }
5608f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5609f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5610f4ddd8eeSStefano Zampini     }
5611365a3a41SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection
5612365a3a41SStefano Zampini        TODO: Get Rid of these conversions */
5613af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5614af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
561504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
561604708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
561704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
561804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
561904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5620af732b37SStefano Zampini       } else {
5621511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
56226816873aSStefano Zampini       }
562304708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
562404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
562504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5626365a3a41SStefano Zampini         ierr = MatConvert(matis->A,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
562704708bb6SStefano Zampini       } else {
5628365a3a41SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
562904708bb6SStefano Zampini       }
563004708bb6SStefano Zampini     }
5631a00504b5SStefano Zampini     /* extract A_RR */
56320aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5633a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5634a00504b5SStefano Zampini 
5635a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
563616e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5637a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
563816e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
563916e386b8SStefano Zampini         } else {
56407dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5641a00504b5SStefano Zampini         }
5642a00504b5SStefano Zampini       } else {
5643a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5644a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5645a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5646a00504b5SStefano Zampini       }
5647a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
56487dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
564916e386b8SStefano Zampini     }
56503301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
5651d1e098c7SStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric);CHKERRQ(ierr);
56526816873aSStefano Zampini     }
565392cccca0SStefano Zampini     opts = PETSC_FALSE;
5654f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
565592cccca0SStefano Zampini       opts = PETSC_TRUE;
5656304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5657304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5658304d26faSStefano Zampini       /* default */
5659304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5660e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5661304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
56629577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
56639577ea80SStefano Zampini       if (issbaij) {
56649577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
56659577ea80SStefano Zampini       } else {
5666304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
56679577ea80SStefano Zampini       }
5668399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure);CHKERRQ(ierr);
566992cccca0SStefano Zampini     }
56702f37b69bSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
567192cccca0SStefano Zampini     ierr = MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix);CHKERRQ(ierr);
567292cccca0SStefano Zampini     if (opts) { /* Allow user's customization once */
5673304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
567492cccca0SStefano Zampini     }
56756d9e27e4SStefano Zampini     ierr = MatGetNearNullSpace(A_RR,&nnsp);CHKERRQ(ierr);
56766d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */
56776d9e27e4SStefano Zampini       ierr = MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR);CHKERRQ(ierr);
567892cccca0SStefano Zampini     }
567992cccca0SStefano Zampini     ierr = MatGetNearNullSpace(A_RR,&nnsp);CHKERRQ(ierr);
568092cccca0SStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5681cd18cfedSStefano Zampini     ierr = PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f);CHKERRQ(ierr);
568292cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5683cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5684cd18cfedSStefano Zampini       const PetscInt *idxs;
5685cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5686cd18cfedSStefano Zampini 
5687cd18cfedSStefano Zampini       ierr = ISGetLocalSize(pcbddc->is_R_local,&nl);CHKERRQ(ierr);
5688cd18cfedSStefano Zampini       ierr = ISGetIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5689cd18cfedSStefano Zampini       ierr = PetscMalloc1(nl*cdim,&scoords);CHKERRQ(ierr);
5690cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5691cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5692cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5693cd18cfedSStefano Zampini         }
5694cd18cfedSStefano Zampini       }
5695cd18cfedSStefano Zampini       ierr = ISRestoreIndices(pcbddc->is_R_local,&idxs);CHKERRQ(ierr);
5696cd18cfedSStefano Zampini       ierr = PCSetCoordinates(pc_temp,cdim,nl,scoords);CHKERRQ(ierr);
5697cd18cfedSStefano Zampini       ierr = PetscFree(scoords);CHKERRQ(ierr);
5698cd18cfedSStefano Zampini     }
569992cccca0SStefano Zampini 
5700304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5701304d26faSStefano Zampini     if (!n_R) {
5702304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5703304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5704304d26faSStefano Zampini     }
5705df4d28bfSStefano Zampini     /* Reuse solver if it is present */
57060aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5707df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5708d62866d3SStefano Zampini 
5709df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5710d62866d3SStefano Zampini     }
571193120301SStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
5712684f6988SStefano Zampini   }
5713304d26faSStefano Zampini 
5714684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5715684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
57161575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5717684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5718684f6988SStefano Zampini   }
57198ead10e4SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
5720c7017625SStefano Zampini 
5721c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
5722c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5723c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5724c7017625SStefano Zampini   }
5725c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
5726c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5727c7017625SStefano Zampini   }
5728c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
5729c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5730c7017625SStefano Zampini   }
5731c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5732c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5733684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
57340fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
57350fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
57360fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
5737c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
57380fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
57390fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5740e604994aSStefano 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);
5741304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5742304d26faSStefano Zampini     }
5743684f6988SStefano Zampini     if (neumann) { /* Neumann */
57440fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
57450fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
57460fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5747c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R);CHKERRQ(ierr);
57480fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
57490fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5750e604994aSStefano 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);
5751304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5752304d26faSStefano Zampini     }
5753684f6988SStefano Zampini   }
57545cbda25cSStefano Zampini   /* free Neumann problem's matrix */
57555cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5756304d26faSStefano Zampini   PetscFunctionReturn(0);
5757304d26faSStefano Zampini }
5758304d26faSStefano Zampini 
575980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5760674ae819SStefano Zampini {
5761674ae819SStefano Zampini   PetscErrorCode  ierr;
5762674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5763be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5764b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
5765674ae819SStefano Zampini 
5766674ae819SStefano Zampini   PetscFunctionBegin;
5767b334f244SStefano Zampini   if (!reuse_solver) {
576880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
576920c7b377SStefano Zampini   }
577080677318SStefano Zampini   if (!pcbddc->switch_static) {
577180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
577280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
577380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
577420c7b377SStefano Zampini     }
5775b334f244SStefano Zampini     if (!reuse_solver) {
577680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
577780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
577820c7b377SStefano Zampini     } else {
5779df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5780be83ff47SStefano Zampini 
5781df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5782df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
578320c7b377SStefano Zampini     }
5784be83ff47SStefano Zampini   } else {
578580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
578680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
578780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
578880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
578980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
579080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
579180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
579280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
579380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5794674ae819SStefano Zampini     }
5795674ae819SStefano Zampini   }
579655c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0);CHKERRQ(ierr);
5797b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
579880677318SStefano Zampini     if (applytranspose) {
579980677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
580080677318SStefano Zampini     } else {
580180677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
580280677318SStefano Zampini     }
5803c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R);CHKERRQ(ierr);
5804be83ff47SStefano Zampini   } else {
5805df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5806be83ff47SStefano Zampini 
5807be83ff47SStefano Zampini     if (applytranspose) {
5808df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5809be83ff47SStefano Zampini     } else {
5810df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5811be83ff47SStefano Zampini     }
5812be83ff47SStefano Zampini   }
581355c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0);CHKERRQ(ierr);
581480677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
581580677318SStefano Zampini   if (!pcbddc->switch_static) {
5816b334f244SStefano Zampini     if (!reuse_solver) {
581780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
581880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5819be83ff47SStefano Zampini     } else {
5820df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5821be83ff47SStefano Zampini 
5822df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5823df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5824be83ff47SStefano Zampini     }
582580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
582680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
582780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
582880677318SStefano Zampini     }
582980677318SStefano Zampini   } else {
583080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
583180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
583280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
583380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
583480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
583580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
583680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
583780677318SStefano Zampini     }
583880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
583980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
584080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
584180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5842674ae819SStefano Zampini   }
5843674ae819SStefano Zampini   PetscFunctionReturn(0);
5844674ae819SStefano Zampini }
5845674ae819SStefano Zampini 
5846dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5847dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5848674ae819SStefano Zampini {
5849674ae819SStefano Zampini   PetscErrorCode ierr;
5850674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5851674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5852674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5853674ae819SStefano Zampini 
5854674ae819SStefano Zampini   PetscFunctionBegin;
5855dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
58564fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5857dc359a40SStefano Zampini     if (applytranspose) {
5858674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
58598eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5860dc359a40SStefano Zampini     } else {
5861674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5862674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
586315aaf578SStefano Zampini     }
58644fee134fSStefano Zampini   } else {
58654fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
58664fee134fSStefano Zampini   }
5867efc2fbd9SStefano Zampini 
5868efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
58694f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5870efc2fbd9SStefano Zampini     PetscScalar *array;
58714f1b2e48SStefano Zampini     PetscInt    j;
5872efc2fbd9SStefano Zampini 
5873efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
58744f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5875efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5876efc2fbd9SStefano Zampini   }
5877efc2fbd9SStefano Zampini 
587812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
587912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
588012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
588112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
588212edc857SStefano Zampini 
58839f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
588412edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
588551694757SStefano Zampini     Mat          coarse_mat;
5886964fefecSStefano Zampini     Vec          rhs,sol;
588751694757SStefano Zampini     MatNullSpace nullsp;
588827b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5889964fefecSStefano Zampini 
589027b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
589127b6a85dSStefano Zampini       PC        coarse_pc;
589227b6a85dSStefano Zampini 
589327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
589427b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
589527b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
589627b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
589727b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
589827b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
58993bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
590027b6a85dSStefano Zampini       }
590127b6a85dSStefano Zampini     }
5902964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5903964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
590451694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
590512edc857SStefano Zampini     if (applytranspose) {
59069a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
590755c176c0SStefano Zampini       ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0);CHKERRQ(ierr);
5908964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
590955c176c0SStefano Zampini       ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0);CHKERRQ(ierr);
5910c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
59119bfcb8eaSStefano Zampini       ierr = MatGetTransposeNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
59129bfcb8eaSStefano Zampini       if (nullsp) {
59139bfcb8eaSStefano Zampini         ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
59149bfcb8eaSStefano Zampini       }
59152701bc32SStefano Zampini     } else {
59169bfcb8eaSStefano Zampini       ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
59171f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
59182701bc32SStefano Zampini         PC        coarse_pc;
59192701bc32SStefano Zampini 
59209bfcb8eaSStefano Zampini         if (nullsp) {
59219bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
59229bfcb8eaSStefano Zampini         }
59232701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
59242701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
59253e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
59262701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
592712edc857SStefano Zampini       } else {
592855c176c0SStefano Zampini         ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0);CHKERRQ(ierr);
5929964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
593055c176c0SStefano Zampini         ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0);CHKERRQ(ierr);
5931c0decd05SBarry Smith         ierr = KSPCheckSolve(pcbddc->coarse_ksp,pc,sol);CHKERRQ(ierr);
59329bfcb8eaSStefano Zampini         if (nullsp) {
59339bfcb8eaSStefano Zampini           ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
59349bfcb8eaSStefano Zampini         }
593512edc857SStefano Zampini       }
59362701bc32SStefano Zampini     }
59371d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
593827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
593927b6a85dSStefano Zampini       PC        coarse_pc;
594027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
594127b6a85dSStefano Zampini 
594227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
594327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
594427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
59453bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
594627b6a85dSStefano Zampini     }
594712edc857SStefano Zampini   }
5948674ae819SStefano Zampini 
5949674ae819SStefano Zampini   /* Local solution on R nodes */
59504fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
595180677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
59529f00e9b4SStefano Zampini   }
59539f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
59549f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
595512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5956674ae819SStefano Zampini 
59574fee134fSStefano Zampini   /* Sum contributions from the two levels */
59584fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5959dc359a40SStefano Zampini     if (applytranspose) {
5960dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5961dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5962dc359a40SStefano Zampini     } else {
5963674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
59648eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5965dc359a40SStefano Zampini     }
5966efc2fbd9SStefano Zampini     /* store p0 */
59674f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5968efc2fbd9SStefano Zampini       PetscScalar *array;
59694f1b2e48SStefano Zampini       PetscInt    j;
5970efc2fbd9SStefano Zampini 
5971efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
59724f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5973efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5974efc2fbd9SStefano Zampini     }
59754fee134fSStefano Zampini   } else { /* expand the coarse solution */
59764fee134fSStefano Zampini     if (applytranspose) {
59774fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
59784fee134fSStefano Zampini     } else {
59794fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
59804fee134fSStefano Zampini     }
59814fee134fSStefano Zampini   }
5982674ae819SStefano Zampini   PetscFunctionReturn(0);
5983674ae819SStefano Zampini }
5984674ae819SStefano Zampini 
598512edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5986674ae819SStefano Zampini {
5987674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
598812edc857SStefano Zampini   Vec               from,to;
59897ebab0bbSStefano Zampini   const PetscScalar *array;
59907ebab0bbSStefano Zampini   PetscErrorCode    ierr;
5991674ae819SStefano Zampini 
5992674ae819SStefano Zampini   PetscFunctionBegin;
599312edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
599412edc857SStefano Zampini     from = pcbddc->coarse_vec;
599512edc857SStefano Zampini     to = pcbddc->vec1_P;
599612edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
599712edc857SStefano Zampini       Vec tvec;
599858da7f69SStefano Zampini 
599958da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
600058da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
600112edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
60027ebab0bbSStefano Zampini       ierr = VecGetArrayRead(tvec,&array);CHKERRQ(ierr);
600358da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
60047ebab0bbSStefano Zampini       ierr = VecRestoreArrayRead(tvec,&array);CHKERRQ(ierr);
600512edc857SStefano Zampini     }
600612edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
600712edc857SStefano Zampini     from = pcbddc->vec1_P;
600812edc857SStefano Zampini     to = pcbddc->coarse_vec;
600912edc857SStefano Zampini   }
601012edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
6011674ae819SStefano Zampini   PetscFunctionReturn(0);
6012674ae819SStefano Zampini }
6013674ae819SStefano Zampini 
601412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
6015674ae819SStefano Zampini {
6016674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
601712edc857SStefano Zampini   Vec               from,to;
60187ebab0bbSStefano Zampini   const PetscScalar *array;
60197ebab0bbSStefano Zampini   PetscErrorCode    ierr;
6020674ae819SStefano Zampini 
6021674ae819SStefano Zampini   PetscFunctionBegin;
602212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
602312edc857SStefano Zampini     from = pcbddc->coarse_vec;
602412edc857SStefano Zampini     to = pcbddc->vec1_P;
602512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
602612edc857SStefano Zampini     from = pcbddc->vec1_P;
602712edc857SStefano Zampini     to = pcbddc->coarse_vec;
602812edc857SStefano Zampini   }
602912edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
603012edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
603112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
603212edc857SStefano Zampini       Vec tvec;
603358da7f69SStefano Zampini 
603412edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
60357ebab0bbSStefano Zampini       ierr = VecGetArrayRead(to,&array);CHKERRQ(ierr);
603658da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
60377ebab0bbSStefano Zampini       ierr = VecRestoreArrayRead(to,&array);CHKERRQ(ierr);
603858da7f69SStefano Zampini     }
603958da7f69SStefano Zampini   } else {
604058da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
604158da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
604212edc857SStefano Zampini     }
604312edc857SStefano Zampini   }
6044674ae819SStefano Zampini   PetscFunctionReturn(0);
6045674ae819SStefano Zampini }
6046674ae819SStefano Zampini 
6047674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
6048674ae819SStefano Zampini {
6049674ae819SStefano Zampini   PetscErrorCode    ierr;
6050674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
6051674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6052674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
6053984c4197SStefano Zampini   /* one and zero */
6054984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
6055984c4197SStefano Zampini   /* space to store constraints and their local indices */
60569162d606SStefano Zampini   PetscScalar       *constraints_data;
60579162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
60589162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
60599162d606SStefano Zampini   PetscInt          *constraints_n;
6060984c4197SStefano Zampini   /* iterators */
6061b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
6062984c4197SStefano Zampini   /* BLAS integers */
6063e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
6064e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
6065c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
6066727cdba6SStefano Zampini   /* reuse */
60670e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
60680e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
6069984c4197SStefano Zampini   /* change of basis */
6070b3d85658SStefano Zampini   PetscBool         qr_needed;
60719162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
6072984c4197SStefano Zampini   /* auxiliary stuff */
607364efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
60748a0068c3SStefano Zampini   PetscInt          ncc;
6075984c4197SStefano Zampini   /* some quantities */
607645a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
6077a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
607857715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
6079984c4197SStefano Zampini 
6080674ae819SStefano Zampini   PetscFunctionBegin;
608157715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
60828e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
60838e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
60848e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
608516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
6086088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
6087088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
60880e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
60890e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
6090580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc);CHKERRQ(ierr);
6091580bdb30SBarry Smith   ierr = PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc);CHKERRQ(ierr);
60920e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
6093088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
6094cf5a6209SStefano Zampini 
6095cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
60969162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
6097cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
6098cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
6099cf5a6209SStefano Zampini     Vec          *localnearnullsp;
6100cf5a6209SStefano Zampini     PetscScalar  *array;
6101cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
6102cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
6103674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
6104b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
6105674ae819SStefano Zampini     PetscScalar  *work;
6106674ae819SStefano Zampini     PetscReal    *singular_vals;
6107674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6108674ae819SStefano Zampini     PetscReal    *rwork;
6109674ae819SStefano Zampini #endif
611055080a34SStefano Zampini     PetscScalar  *temp_basis = NULL,*correlation_mat = NULL;
6111964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
6112964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
611355080a34SStefano Zampini     PetscBool    use_pod = PETSC_FALSE;
6114674ae819SStefano Zampini 
611555080a34SStefano Zampini     /* MKL SVD with same input gives different results on different processes! */
611655080a34SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL)
611755080a34SStefano Zampini     use_pod = PETSC_TRUE;
611855080a34SStefano Zampini #endif
6119674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
6120d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
6121e4d548c7SStefano Zampini     /* print some info */
61225c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
6123e4d548c7SStefano Zampini       PetscInt nv;
6124e4d548c7SStefano Zampini 
6125c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6126e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
6127e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6128e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
61296080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
61306080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
61316080607fSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
6132e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6133e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6134e4d548c7SStefano Zampini     }
6135e4d548c7SStefano Zampini 
6136d06fc5fdSStefano Zampini     /* free unneeded index sets */
6137d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
6138d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
6139674ae819SStefano Zampini     }
6140d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
6141d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
6142d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6143d06fc5fdSStefano Zampini       }
6144d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6145d06fc5fdSStefano Zampini       n_ISForEdges = 0;
6146d06fc5fdSStefano Zampini     }
6147d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
6148d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
6149d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6150d06fc5fdSStefano Zampini       }
6151d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6152d06fc5fdSStefano Zampini       n_ISForFaces = 0;
6153d06fc5fdSStefano Zampini     }
615470022509SStefano Zampini 
6155674ae819SStefano Zampini     /* check if near null space is attached to global mat */
61566d9e27e4SStefano Zampini     if (pcbddc->use_nnsp) {
6157674ae819SStefano Zampini       ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
61586d9e27e4SStefano Zampini     } else nearnullsp = NULL;
61596d9e27e4SStefano Zampini 
6160674ae819SStefano Zampini     if (nearnullsp) {
6161674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
6162f4ddd8eeSStefano Zampini       /* remove any stored info */
6163f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
6164f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6165f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
6166f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
6167f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
6168473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
6169f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
6170f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
6171f4ddd8eeSStefano Zampini       }
6172984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
6173984c4197SStefano Zampini       nnsp_size = 0;
6174674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
6175674ae819SStefano Zampini     }
6176984c4197SStefano Zampini     /* get max number of constraints on a single cc */
6177984c4197SStefano Zampini     max_constraints = nnsp_size;
6178984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
6179984c4197SStefano Zampini 
6180674ae819SStefano Zampini     /*
6181674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
61829162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
61839162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
61849162d606SStefano Zampini          There can be multiple constraints per connected component
6185674ae819SStefano Zampini                                                                                                                                                            */
6186674ae819SStefano Zampini     n_vertices = 0;
6187674ae819SStefano Zampini     if (ISForVertices) {
6188674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
6189674ae819SStefano Zampini     }
61909162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
61919162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
61929162d606SStefano Zampini 
61939162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
61949162d606SStefano Zampini     total_counts *= max_constraints;
6195674ae819SStefano Zampini     total_counts += n_vertices;
61964641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
61979162d606SStefano Zampini 
6198674ae819SStefano Zampini     total_counts = 0;
6199674ae819SStefano Zampini     max_size_of_constraint = 0;
6200674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
62019162d606SStefano Zampini       IS used_is;
6202674ae819SStefano Zampini       if (i<n_ISForEdges) {
62039162d606SStefano Zampini         used_is = ISForEdges[i];
6204674ae819SStefano Zampini       } else {
62059162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
6206674ae819SStefano Zampini       }
62079162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
6208674ae819SStefano Zampini       total_counts += j;
6209674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
6210674ae819SStefano Zampini     }
62119162d606SStefano 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);
62129162d606SStefano Zampini 
6213984c4197SStefano Zampini     /* get local part of global near null space vectors */
6214785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
6215984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6216984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
6217e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6218e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6219984c4197SStefano Zampini     }
6220674ae819SStefano Zampini 
6221242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
6222242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
6223a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
6224242a89d7SStefano Zampini 
6225984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
6226a773dcb8SStefano Zampini     if (!skip_lapack) {
6227674ae819SStefano Zampini       PetscScalar temp_work;
6228911cabfeSStefano Zampini 
622955080a34SStefano Zampini       if (use_pod) {
6230984c4197SStefano Zampini         /* Proper Orthogonal Decomposition (POD) using the snapshot method */
6231785e854fSJed Brown         ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
6232785e854fSJed Brown         ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
6233785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
6234674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6235785e854fSJed Brown         ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
6236674ae819SStefano Zampini #endif
6237674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6238c8244a33SStefano Zampini         ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
6239c8244a33SStefano Zampini         ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
6240674ae819SStefano Zampini         lwork = -1;
6241674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6242674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6243c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6244674ae819SStefano Zampini #else
6245c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6246674ae819SStefano Zampini #endif
6247674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
6248984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
624955080a34SStefano Zampini       } else {
625055080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6251674ae819SStefano Zampini         /* SVD */
6252674ae819SStefano Zampini         PetscInt max_n,min_n;
6253674ae819SStefano Zampini         max_n = max_size_of_constraint;
6254984c4197SStefano Zampini         min_n = max_constraints;
6255984c4197SStefano Zampini         if (max_size_of_constraint < max_constraints) {
6256674ae819SStefano Zampini           min_n = max_size_of_constraint;
6257984c4197SStefano Zampini           max_n = max_constraints;
6258674ae819SStefano Zampini         }
6259785e854fSJed Brown         ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
6260674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6261785e854fSJed Brown         ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
6262674ae819SStefano Zampini #endif
6263674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6264674ae819SStefano Zampini         lwork = -1;
6265e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
6266e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
6267b7d8b9f8SStefano Zampini         ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
6268674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6269674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
62709162d606SStefano 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));
6271674ae819SStefano Zampini #else
62729162d606SStefano 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));
6273674ae819SStefano Zampini #endif
6274674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
6275984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
627655080a34SStefano Zampini #else
627755080a34SStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6278984c4197SStefano Zampini #endif /* on missing GESVD */
627955080a34SStefano Zampini       }
6280674ae819SStefano Zampini       /* Allocate optimal workspace */
6281674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
6282854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
6283674ae819SStefano Zampini     }
6284674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6285674ae819SStefano Zampini     total_counts = 0;
62869162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
62879162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6288674ae819SStefano Zampini     /* vertices */
62899162d606SStefano Zampini     if (n_vertices) {
6290674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6291580bdb30SBarry Smith       ierr = PetscArraycpy(constraints_idxs,is_indices,n_vertices);CHKERRQ(ierr);
6292674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
62939162d606SStefano Zampini         constraints_n[total_counts] = 1;
62949162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
62959162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
62969162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6297674ae819SStefano Zampini         total_counts++;
6298674ae819SStefano Zampini       }
6299674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6300674ae819SStefano Zampini       n_vertices = total_counts;
6301674ae819SStefano Zampini     }
6302984c4197SStefano Zampini 
6303674ae819SStefano Zampini     /* edges and faces */
63049162d606SStefano Zampini     total_counts_cc = total_counts;
6305911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
63069162d606SStefano Zampini       IS        used_is;
63079162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
63089162d606SStefano Zampini 
6309911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
63109162d606SStefano Zampini         used_is = ISForEdges[ncc];
6311984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6312674ae819SStefano Zampini       } else {
63139162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6314984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6315674ae819SStefano Zampini       }
6316674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
63179162d606SStefano Zampini 
63189162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
63199162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6320984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6321984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6322674ae819SStefano Zampini       if (nnsp_has_cnst) {
63235b08dc53SStefano Zampini         PetscScalar quad_value;
63249162d606SStefano Zampini 
6325580bdb30SBarry Smith         ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
63269162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
63279162d606SStefano Zampini 
6328a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6329674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6330a773dcb8SStefano Zampini         } else {
6331a773dcb8SStefano Zampini           quad_value = 1.0;
6332a773dcb8SStefano Zampini         }
6333674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63349162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6335674ae819SStefano Zampini         }
63369162d606SStefano Zampini         temp_constraints++;
6337674ae819SStefano Zampini         total_counts++;
6338674ae819SStefano Zampini       }
6339674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6340984c4197SStefano Zampini         PetscReal real_value;
63419162d606SStefano Zampini         PetscScalar *ptr_to_data;
63429162d606SStefano Zampini 
6343984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
63449162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6345674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63469162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6347674ae819SStefano Zampini         }
6348984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
6349984c4197SStefano Zampini         /* check if array is null on the connected component */
6350e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63519162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
635257715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6353674ae819SStefano Zampini           temp_constraints++;
6354674ae819SStefano Zampini           total_counts++;
63559162d606SStefano Zampini           if (!idxs_copied) {
6356580bdb30SBarry Smith             ierr = PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint);CHKERRQ(ierr);
63579162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6358674ae819SStefano Zampini           }
6359674ae819SStefano Zampini         }
63609162d606SStefano Zampini       }
63619162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
636245a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6363eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6364a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
63659162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
63669162d606SStefano Zampini 
63679162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6368a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63699162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6370a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
63719162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6372a773dcb8SStefano Zampini         } else { /* perform SVD */
63739162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6374674ae819SStefano Zampini 
637555080a34SStefano Zampini           if (use_pod) {
6376984c4197SStefano Zampini             /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6377984c4197SStefano Zampini                POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6378984c4197SStefano Zampini                -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6379984c4197SStefano Zampini                   the constraints basis will differ (by a complex factor with absolute value equal to 1)
6380984c4197SStefano Zampini                   from that computed using LAPACKgesvd
6381984c4197SStefano Zampini                -> This is due to a different computation of eigenvectors in LAPACKheev
6382984c4197SStefano Zampini                -> The quality of the POD-computed basis will be the same */
6383580bdb30SBarry Smith             ierr = PetscArrayzero(correlation_mat,temp_constraints*temp_constraints);CHKERRQ(ierr);
6384674ae819SStefano Zampini             /* Store upper triangular part of correlation matrix */
6385e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6386984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6387674ae819SStefano Zampini             for (j=0;j<temp_constraints;j++) {
6388674ae819SStefano Zampini               for (k=0;k<j+1;k++) {
63899162d606SStefano 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));
6390674ae819SStefano Zampini               }
6391674ae819SStefano Zampini             }
6392e310c8b4SStefano Zampini             /* compute eigenvalues and eigenvectors of correlation matrix */
6393e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6394e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
6395674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6396c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6397674ae819SStefano Zampini #else
6398c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6399674ae819SStefano Zampini #endif
6400674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6401984c4197SStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6402984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6403674ae819SStefano Zampini             j = 0;
640487b3baaaSStefano Zampini             while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6405674ae819SStefano Zampini             total_counts = total_counts-j;
640645a1bb75SStefano Zampini             valid_constraints = temp_constraints-j;
6407e310c8b4SStefano Zampini             /* scale and copy POD basis into used quadrature memory */
6408c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6409c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6410c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
6411c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6412c4303822SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
6413c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6414674ae819SStefano Zampini             if (j<temp_constraints) {
6415984c4197SStefano Zampini               PetscInt ii;
6416984c4197SStefano Zampini               for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
6417674ae819SStefano Zampini               ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64189162d606SStefano 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));
6419674ae819SStefano Zampini               ierr = PetscFPTrapPop();CHKERRQ(ierr);
6420984c4197SStefano Zampini               for (k=0;k<temp_constraints-j;k++) {
6421674ae819SStefano Zampini                 for (ii=0;ii<size_of_constraint;ii++) {
64229162d606SStefano 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];
6423674ae819SStefano Zampini                 }
6424674ae819SStefano Zampini               }
6425674ae819SStefano Zampini             }
642655080a34SStefano Zampini           } else {
642755080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6428e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
6429e310c8b4SStefano Zampini             ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
6430b7d8b9f8SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6431674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6432674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
64339162d606SStefano 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));
6434674ae819SStefano Zampini #else
64359162d606SStefano 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));
6436674ae819SStefano Zampini #endif
6437984c4197SStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
6438674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6439984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6440e310c8b4SStefano Zampini             k = temp_constraints;
6441e310c8b4SStefano Zampini             if (k > size_of_constraint) k = size_of_constraint;
6442674ae819SStefano Zampini             j = 0;
644387b3baaaSStefano Zampini             while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
644445a1bb75SStefano Zampini             valid_constraints = k-j;
6445911cabfeSStefano Zampini             total_counts = total_counts-temp_constraints+valid_constraints;
644655080a34SStefano Zampini #else
644755080a34SStefano Zampini             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6448984c4197SStefano Zampini #endif /* on missing GESVD */
6449674ae819SStefano Zampini           }
6450a773dcb8SStefano Zampini         }
645155080a34SStefano Zampini       }
64529162d606SStefano Zampini       /* update pointers information */
64539162d606SStefano Zampini       if (valid_constraints) {
64549162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
64559162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
64569162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
64579162d606SStefano Zampini         /* set change_of_basis flag */
645845a1bb75SStefano Zampini         if (boolforchange) {
6459b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
64609162d606SStefano Zampini         }
6461b3d85658SStefano Zampini         total_counts_cc++;
646245a1bb75SStefano Zampini       }
646345a1bb75SStefano Zampini     }
6464984c4197SStefano Zampini     /* free workspace */
64658f1c130eSStefano Zampini     if (!skip_lapack) {
6466984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
6467984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6468984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
6469984c4197SStefano Zampini #endif
6470984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
6471984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
6472984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
6473984c4197SStefano Zampini     }
6474984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
6475984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
6476984c4197SStefano Zampini     }
6477984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
6478cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6479cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
6480cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
6481cf5a6209SStefano Zampini     }
6482cf5a6209SStefano Zampini     if (n_ISForFaces) {
6483cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
6484cf5a6209SStefano Zampini     }
6485cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
6486cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
6487cf5a6209SStefano Zampini     }
6488cf5a6209SStefano Zampini     if (n_ISForEdges) {
6489cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
6490cf5a6209SStefano Zampini     }
6491cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
649208122e43SStefano Zampini   } else {
649308122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6494984c4197SStefano Zampini 
649508122e43SStefano Zampini     total_counts = 0;
649608122e43SStefano Zampini     n_vertices = 0;
6497d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
6498d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
649908122e43SStefano Zampini     }
650008122e43SStefano Zampini     max_constraints = 0;
65019162d606SStefano Zampini     total_counts_cc = 0;
650208122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
650308122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
65049162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
650508122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
650608122e43SStefano Zampini     }
65079162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
65089162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
65099162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
65109162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
651174d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
65129162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
65139162d606SStefano Zampini     total_counts_cc = 0;
65149162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
65159162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
65169162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
651708122e43SStefano Zampini       }
651808122e43SStefano Zampini     }
651908122e43SStefano Zampini 
65208bec7fa6SStefano Zampini     max_size_of_constraint = 0;
65219162d606SStefano 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]);
65229162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
652308122e43SStefano Zampini     /* Change of basis */
6524b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
652508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
652608122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
652708122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
6528b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
652908122e43SStefano Zampini         }
653008122e43SStefano Zampini       }
653108122e43SStefano Zampini     }
653208122e43SStefano Zampini   }
6533984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
65344f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
653508122e43SStefano Zampini 
65369162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
65379162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
65386080607fSStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %D != %D",constraints_idxs_ptr[total_counts_cc],i);
6539674ae819SStefano Zampini 
6540674ae819SStefano Zampini   /* Create constraint matrix */
6541674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
654216f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6543984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6544984c4197SStefano Zampini 
6545984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6546a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
65475a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
654874d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6549984c4197SStefano Zampini   total_primal_vertices=0;
6550b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
65519162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
65529162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
655372b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
65549162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6555b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
655664efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
65579162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65589162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6559a717540cSStefano Zampini       }
6560b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
656191af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6562a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6563a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6564a717540cSStefano Zampini       }
6565fa434743SStefano Zampini     } else {
6566b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6567fa434743SStefano Zampini     }
6568a717540cSStefano Zampini   }
6569b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6570b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6571674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
657270022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
65734f1b2e48SStefano 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);
6574580bdb30SBarry Smith   ierr = PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices);CHKERRQ(ierr);
65750e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6576984c4197SStefano Zampini 
6577984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
657874d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6579785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6580984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
658174d5cdf7SStefano Zampini 
6582984c4197SStefano Zampini   j = total_primal_vertices;
658374d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6584b3d85658SStefano Zampini   cum = total_primal_vertices;
65859162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65864641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6587b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6588b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6589b3d85658SStefano Zampini       cum++;
65909162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
659174d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
659274d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
659374d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
659474d5cdf7SStefano Zampini       }
65959162d606SStefano Zampini       j += constraints_n[i];
6596674ae819SStefano Zampini     }
6597674ae819SStefano Zampini   }
6598674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6599e1b21442SStefano Zampini   ierr = MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6600674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6601088faed8SStefano Zampini 
6602674ae819SStefano Zampini   /* set values in constraint matrix */
6603984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
66040e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6605674ae819SStefano Zampini   }
6606984c4197SStefano Zampini   total_counts = total_primal_vertices;
66079162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
66084641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
66099162d606SStefano Zampini       PetscInt *cols;
66109162d606SStefano Zampini 
66119162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
66129162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
66139162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
66149162d606SStefano Zampini         PetscInt    row = total_counts+k;
66159162d606SStefano Zampini         PetscScalar *vals;
66169162d606SStefano Zampini 
66179162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
66189162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
66199162d606SStefano Zampini       }
66209162d606SStefano Zampini       total_counts += constraints_n[i];
6621674ae819SStefano Zampini     }
6622674ae819SStefano Zampini   }
6623674ae819SStefano Zampini   /* assembling */
6624674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6625674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66267ebab0bbSStefano Zampini   ierr = MatViewFromOptions(pcbddc->ConstraintMatrix,(PetscObject)pc,"-pc_bddc_constraint_mat_view");CHKERRQ(ierr);
6627088faed8SStefano Zampini 
6628674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6629674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6630026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6631984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6632984c4197SStefano Zampini     /* working stuff for GEQRF */
66335a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6634984c4197SStefano Zampini     PetscBLASInt lqr_work;
6635984c4197SStefano Zampini     /* working stuff for UNGQR */
66363c377650SSatish Balay     PetscScalar  *gqr_work = NULL,lgqr_work_t=0.0;
6637984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6638984c4197SStefano Zampini     /* working stuff for TRTRS */
66395a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
66403f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6641984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6642984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6643984c4197SStefano Zampini     PetscScalar  *start_vals;
6644984c4197SStefano Zampini     /* working stuff for values insertion */
66454641a718SStefano Zampini     PetscBT      is_primal;
664664efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6647906d46d4SStefano Zampini     /* matrix sizes */
6648906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6649906d46d4SStefano Zampini     /* temporary change of basis */
6650906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6651cf5a6209SStefano Zampini     /* extra space for debugging */
66525a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6653984c4197SStefano Zampini 
6654906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6655906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
665616f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6657bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6658906d46d4SStefano Zampini     /* nonzeros for local mat */
6659bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
66601dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6661bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
66621dd7afcfSStefano Zampini     } else {
66631dd7afcfSStefano Zampini       const PetscInt *ii;
66641dd7afcfSStefano Zampini       PetscInt       n;
66651dd7afcfSStefano Zampini       PetscBool      flg_row;
66661dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
66671dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
66681dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
66691dd7afcfSStefano Zampini     }
66709162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6671a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
66729162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6673a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
66749162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6675a717540cSStefano Zampini         } else {
66769162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
66779162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6678a717540cSStefano Zampini         }
6679a717540cSStefano Zampini       }
6680a717540cSStefano Zampini     }
6681906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6682e1b21442SStefano Zampini     ierr = MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
6683bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
66841dd7afcfSStefano Zampini     /* Set interior change in the matrix */
66851dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6686bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6687906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6688a717540cSStefano Zampini       }
66891dd7afcfSStefano Zampini     } else {
66901dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
66911dd7afcfSStefano Zampini       PetscScalar    *aa;
66921dd7afcfSStefano Zampini       PetscInt       n;
66931dd7afcfSStefano Zampini       PetscBool      flg_row;
66941dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
66951dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
66961dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
66971dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
66981dd7afcfSStefano Zampini       }
66991dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
67001dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
67011dd7afcfSStefano Zampini     }
6702a717540cSStefano Zampini 
6703a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6704a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6705a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6706a717540cSStefano Zampini     }
6707a717540cSStefano Zampini 
6708a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6709a717540cSStefano Zampini     /*
6710a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6711a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6712a717540cSStefano Zampini 
6713a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6714a717540cSStefano Zampini 
6715a6b551f4SStefano 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)
6716a6b551f4SStefano Zampini 
6717a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6718a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6719a717540cSStefano Zampini             |              ...                        |
6720a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6721a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6722a717540cSStefano Zampini 
6723a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6724a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6725a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6726a6b551f4SStefano Zampini 
6727a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6728a717540cSStefano Zampini     */
67295a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6730984c4197SStefano Zampini       /* space to store Q */
6731854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
67324e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
67334e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6734984c4197SStefano Zampini       /* first we issue queries for optimal work */
67353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
67363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
67373f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6738984c4197SStefano Zampini       lqr_work = -1;
67393f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6740984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6741984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6742785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6743984c4197SStefano Zampini       lgqr_work = -1;
67443f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
67453f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
67463f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
67473f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
67483f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6749c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6750c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6751984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6752785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6753984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6754785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6755a717540cSStefano Zampini       /* allocating workspace for check */
6756a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6757cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6758a717540cSStefano Zampini       }
6759a717540cSStefano Zampini     }
6760984c4197SStefano Zampini     /* array to store whether a node is primal or not */
67614641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6762473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
67630e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
67646080607fSStefano Zampini     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",total_primal_vertices,i);
676539e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
676639e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
676739e2fb2aSStefano Zampini     }
676839e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6769984c4197SStefano Zampini 
6770a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
67719162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
67729162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
67734641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6774984c4197SStefano Zampini         /* get constraint info */
67759162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6776984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6777984c4197SStefano Zampini 
6778984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
67796080607fSStefano 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);
6780674ae819SStefano Zampini         }
6781984c4197SStefano Zampini 
6782fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6783a717540cSStefano Zampini 
6784a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6785a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
6786580bdb30SBarry Smith             ierr = PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6787a717540cSStefano Zampini           }
6788984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
6789580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6790984c4197SStefano Zampini 
6791984c4197SStefano Zampini           /* compute QR decomposition of constraints */
67923f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
67933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
67943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6795674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
67963f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6797984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6798674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6799984c4197SStefano Zampini 
6800a5b23f4aSJose E. Roman           /* explicitly compute R^-T */
6801580bdb30SBarry Smith           ierr = PetscArrayzero(trs_rhs,primal_dofs*primal_dofs);CHKERRQ(ierr);
6802984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
68033f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
68043f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
68053f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
68063f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6807984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
68083f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6809984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6810984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6811984c4197SStefano Zampini 
6812a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */
68133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
68143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
68153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
68163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6817984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6818c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6819c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6820984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6821984c4197SStefano Zampini 
6822984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6823984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6824984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
68253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
68263f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
68273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
68283f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
68293f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
68303f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6831984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
68329162d606SStefano 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));
6833984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6834580bdb30SBarry Smith           ierr = PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs);CHKERRQ(ierr);
6835984c4197SStefano Zampini 
6836984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
68379162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6838984c4197SStefano Zampini           /* insert cols for primal dofs */
6839984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6840984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
68419162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6842906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6843984c4197SStefano Zampini           }
6844984c4197SStefano Zampini           /* insert cols for dual dofs */
6845984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
68469162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6847984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
68489162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6849906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6850984c4197SStefano Zampini               j++;
6851674ae819SStefano Zampini             }
6852674ae819SStefano Zampini           }
6853984c4197SStefano Zampini 
6854984c4197SStefano Zampini           /* check change of basis */
6855984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6856984c4197SStefano Zampini             PetscInt   ii,jj;
6857984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6858c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6859c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6860c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6861c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6862c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6863c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6864984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6865cf5a6209SStefano 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));
6866984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6867984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6868984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6869cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6870c068d9bbSLisandro 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;
6871674ae819SStefano Zampini               }
6872674ae819SStefano Zampini             }
6873984c4197SStefano Zampini             if (!valid_qr) {
687422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6875984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6876984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6877cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
68786080607fSStefano Zampini                     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %D is not orthogonal to constraint %D (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));CHKERRQ(ierr);
6879674ae819SStefano Zampini                   }
6880c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
68816080607fSStefano Zampini                     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %D is not unitary w.r.t constraint %D (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));CHKERRQ(ierr);
6882984c4197SStefano Zampini                   }
6883984c4197SStefano Zampini                 }
6884984c4197SStefano Zampini               }
6885674ae819SStefano Zampini             } else {
688622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6887674ae819SStefano Zampini             }
6888674ae819SStefano Zampini           }
6889a717540cSStefano Zampini         } else { /* simple transformation block */
6890a717540cSStefano Zampini           PetscInt    row,col;
6891a6b551f4SStefano Zampini           PetscScalar val,norm;
6892a6b551f4SStefano Zampini 
6893a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
68949162d606SStefano 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));
6895a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
68969162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
68979162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6898bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
68999162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6900906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
69019162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6902a717540cSStefano Zampini             } else {
6903a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
69049162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6905a717540cSStefano Zampini                 if (row != col) {
69069162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6907a717540cSStefano Zampini                 } else {
69089162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6909a717540cSStefano Zampini                 }
6910906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6911a717540cSStefano Zampini               }
6912a717540cSStefano Zampini             }
6913a717540cSStefano Zampini           }
691498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
691522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6916a717540cSStefano Zampini           }
6917674ae819SStefano Zampini         }
6918984c4197SStefano Zampini       } else {
6919984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
69206080607fSStefano 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);
6921674ae819SStefano Zampini         }
6922674ae819SStefano Zampini       }
6923674ae819SStefano Zampini     }
6924a717540cSStefano Zampini 
6925a717540cSStefano Zampini     /* free workspace */
6926a717540cSStefano Zampini     if (qr_needed) {
6927984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6928cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6929984c4197SStefano Zampini       }
6930984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6931984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6932984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6933984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6934984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6935674ae819SStefano Zampini     }
6936a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6937906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6938906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6939906d46d4SStefano Zampini 
6940906d46d4SStefano Zampini     /* assembling of global change of variable */
694188c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6942bbb9e6c6SStefano Zampini       Mat      tmat;
694316f15bc4SStefano Zampini       PetscInt bs;
694416f15bc4SStefano Zampini 
6945906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6946906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6947bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6948bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6949487b449aSStefano Zampini       ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6950487b449aSStefano Zampini       ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6951bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6952bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
695316f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
695416f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6955906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6956bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6957487b449aSStefano Zampini       ierr = MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6958bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6959bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6960bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6961e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6962e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6963bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6964bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
696588c03ad3SStefano Zampini 
6966906d46d4SStefano Zampini       /* check */
6967906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6968906d46d4SStefano Zampini         PetscReal error;
6969906d46d4SStefano Zampini         Vec       x,x_change;
6970906d46d4SStefano Zampini 
6971906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6972906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6973906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6974906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6975e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6976e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6977bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6978e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6979e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6980906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6981906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6982906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6983637e8532SStefano Zampini         if (error > PETSC_SMALL) {
69846080607fSStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error);
6985637e8532SStefano Zampini         }
6986906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6987906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6988906d46d4SStefano Zampini       }
6989b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6990b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6991b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6992bf3a8328SStefano Zampini 
699313903a91SSatish 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");
6994b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6995ac632422SStefano Zampini           Mat                    S_new,tmat;
6996bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6997bbb9e6c6SStefano Zampini 
6998bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
69997dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
7000bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
7001bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
7002bf3a8328SStefano Zampini             IS                     is_V;
7003b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
7004b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
7005b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
7006b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
7007b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
7008bf3a8328SStefano Zampini           }
7009bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
7010ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
7011b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
7012ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
7013bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
7014bf3a8328SStefano Zampini             const PetscScalar *array;
7015bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
7016bf3a8328SStefano Zampini             PetscInt          i,n_V;
7017bf3a8328SStefano Zampini 
7018b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
7019b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
7020b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
7021b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
7022b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
7023b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
7024b087196eSStefano Zampini               PetscScalar val;
7025b087196eSStefano Zampini               PetscInt    idx;
7026b087196eSStefano Zampini 
7027b087196eSStefano Zampini               idx = idxs_V[i];
7028b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
7029b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
7030b087196eSStefano Zampini             }
7031b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7032b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7033bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
7034bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
7035bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
7036bf3a8328SStefano Zampini           }
7037ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
7038ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
7039ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
7040ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
7041b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
7042ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
7043bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
7044b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
7045bf3a8328SStefano Zampini             }
7046ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
7047ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
7048ac632422SStefano Zampini           }
7049b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
705088c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
7051b96c3477SStefano Zampini         }
7052c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
7053b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
7054c9db6a07SStefano Zampini           PetscInt i;
7055c9db6a07SStefano Zampini 
7056c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
7057c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
7058c9db6a07SStefano Zampini           }
7059c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
7060c9db6a07SStefano Zampini         }
7061b96c3477SStefano Zampini       }
706216909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
706316909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
706416909a7fSStefano Zampini       } else {
7065906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
706616909a7fSStefano Zampini       }
70671dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
706827b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
706972b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
707072b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
707172b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
707272b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
707372b8c272SStefano Zampini     }
70741dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
707527b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
7076b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
7077b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
7078906d46d4SStefano Zampini     } else {
70791dd7afcfSStefano Zampini       Mat benign_global = NULL;
708027b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
70811dd7afcfSStefano Zampini         Mat M;
70821dd7afcfSStefano Zampini 
70839e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
70849e9b7b1fSStefano Zampini         ierr = VecCopy(matis->counter,pcis->vec1_N);CHKERRQ(ierr);
70859e9b7b1fSStefano Zampini         ierr = VecReciprocal(pcis->vec1_N);CHKERRQ(ierr);
70869e9b7b1fSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global);CHKERRQ(ierr);
70879e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
70881dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
70891dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
7090906d46d4SStefano Zampini         } else {
70919e9b7b1fSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M);CHKERRQ(ierr);
70929e9b7b1fSStefano Zampini           ierr = MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES);CHKERRQ(ierr);
7093906d46d4SStefano Zampini         }
70949e9b7b1fSStefano Zampini         ierr = MatISSetLocalMat(benign_global,M);CHKERRQ(ierr);
70959e9b7b1fSStefano Zampini         ierr = MatDestroy(&M);CHKERRQ(ierr);
70969e9b7b1fSStefano Zampini         ierr = MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70979e9b7b1fSStefano Zampini         ierr = MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70981dd7afcfSStefano Zampini       }
70991dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
71001dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
71011dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
710227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
71031dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
71041dd7afcfSStefano Zampini       }
71051dd7afcfSStefano Zampini     }
710616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
710716909a7fSStefano Zampini       IS             is_global;
710816909a7fSStefano Zampini       const PetscInt *gidxs;
710916909a7fSStefano Zampini 
711016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
711116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
711216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
71137dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
711416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
711516909a7fSStefano Zampini     }
71161dd7afcfSStefano Zampini   }
71171dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
71181dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
7119b9b85e73SStefano Zampini   }
7120a717540cSStefano Zampini 
712172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
71224f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
71234f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
71244f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
71254f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
7126019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
7127019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
7128019a44ceSStefano Zampini       pcbddc->local_primal_size++;
7129019a44ceSStefano Zampini     }
7130019a44ceSStefano Zampini 
7131019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
7132727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
7133727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
7134580bdb30SBarry Smith       ierr = PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7135c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
71360e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
7137580bdb30SBarry Smith         ierr = PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
7138727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
7139727cdba6SStefano Zampini       }
71400e6343abSStefano Zampini     }
7141727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
7142820f2d46SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
714372b8c272SStefano Zampini   }
714472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
7145727cdba6SStefano Zampini 
7146a717540cSStefano Zampini   /* flush dbg viewer */
7147b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
7148b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7149b8ffe317SStefano Zampini   }
7150a717540cSStefano Zampini 
7151e310c8b4SStefano Zampini   /* free workspace */
7152a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
71534641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
715408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
71559162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
71569162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
715708122e43SStefano Zampini   } else {
71589162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
71599162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
71609162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
716108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
716208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
71639162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
71649162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
716508122e43SStefano Zampini   }
7166674ae819SStefano Zampini   PetscFunctionReturn(0);
7167674ae819SStefano Zampini }
7168674ae819SStefano Zampini 
7169674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
7170674ae819SStefano Zampini {
717171582508SStefano Zampini   ISLocalToGlobalMapping map;
7172674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7173674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
717466da6bd7Sstefano_zampini   PetscInt               i,N;
717566da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
717666da6bd7Sstefano_zampini   PetscErrorCode         ierr;
7177674ae819SStefano Zampini 
7178674ae819SStefano Zampini   PetscFunctionBegin;
71798af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
7180b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
71818e61c736SStefano Zampini     /* Reset previously computed graph */
71828e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
7183674ae819SStefano Zampini     /* Init local Graph struct */
71847fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
718571582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
7186be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
7187674ae819SStefano Zampini 
71887a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
71897a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
71907a0e7b2cSstefano_zampini     }
7191575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
71926080607fSStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %D, expected %D",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
71939577ea80SStefano Zampini 
7194674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
719566da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
71964d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
71974d379d7bSStefano Zampini       PetscInt  nvtxs;
7198e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
7199674ae819SStefano Zampini 
72002fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
72012fffb893SStefano Zampini       if (flg_row) {
72024d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
7203b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
72042fffb893SStefano Zampini       }
72052fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
720666da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
7207674ae819SStefano Zampini     }
72089b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
72099b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7210674ae819SStefano Zampini     }
7211674ae819SStefano Zampini 
7212ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
7213ab8c8b98SStefano Zampini       PetscReal    *lcoords;
7214ab8c8b98SStefano Zampini       PetscInt     n;
7215ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
7216ab8c8b98SStefano Zampini 
72174f819b78SStefano Zampini       /* TODO: support for blocked */
7218ab8c8b98SStefano 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);
7219ab8c8b98SStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
7220ab8c8b98SStefano Zampini       ierr = PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords);CHKERRQ(ierr);
7221ffc4695bSBarry Smith       ierr = MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype);CHKERRMPI(ierr);
7222ffc4695bSBarry Smith       ierr = MPI_Type_commit(&dimrealtype);CHKERRMPI(ierr);
7223ad227feaSJunchao Zhang       ierr = PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE);CHKERRQ(ierr);
7224ad227feaSJunchao Zhang       ierr = PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE);CHKERRQ(ierr);
7225ffc4695bSBarry Smith       ierr = MPI_Type_free(&dimrealtype);CHKERRMPI(ierr);
7226ab8c8b98SStefano Zampini       ierr = PetscFree(pcbddc->mat_graph->coords);CHKERRQ(ierr);
7227ab8c8b98SStefano Zampini 
7228ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
7229ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
7230ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
7231ab8c8b98SStefano Zampini     }
7232ab8c8b98SStefano 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);
7233625961bdSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected);
7234ab8c8b98SStefano Zampini 
7235674ae819SStefano Zampini     /* Setup of Graph */
72364b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
723714f95afaSStefano 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);
7238674ae819SStefano Zampini 
72394f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
72404f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
724120c3699dSStefano Zampini       PetscInt *local_subs,n,totn;
72424f1b2e48SStefano Zampini 
724320c3699dSStefano Zampini       ierr = MatGetLocalSize(matis->A,&n,NULL);CHKERRQ(ierr);
724420c3699dSStefano Zampini       ierr = PetscMalloc1(n,&local_subs);CHKERRQ(ierr);
724520c3699dSStefano Zampini       for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs;
72464f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
72474f1b2e48SStefano Zampini         const PetscInt *idxs;
72484f1b2e48SStefano Zampini         PetscInt       nl,j;
72494f1b2e48SStefano Zampini 
72504f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
72514f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
725271582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
72534f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
72544f1b2e48SStefano Zampini       }
725520c3699dSStefano Zampini       for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]);
725620c3699dSStefano Zampini       pcbddc->mat_graph->n_local_subs = totn + 1;
72574f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
72584f1b2e48SStefano Zampini     }
72598af8fcf9SStefano Zampini   }
72604f1b2e48SStefano Zampini 
7261cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7262674ae819SStefano Zampini     /* Graph's connected components analysis */
7263674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
726471582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
72654f819b78SStefano Zampini     pcbddc->corner_selected = pcbddc->corner_selection;
72668af8fcf9SStefano Zampini   }
726766da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7268674ae819SStefano Zampini   PetscFunctionReturn(0);
7269674ae819SStefano Zampini }
7270674ae819SStefano Zampini 
7271295df10fSStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[])
72729a7d3425SStefano Zampini {
7273295df10fSStefano Zampini   PetscInt       i,j,n;
72749a7d3425SStefano Zampini   PetscScalar    *alphas;
7275295df10fSStefano Zampini   PetscReal      norm,*onorms;
72769a7d3425SStefano Zampini   PetscErrorCode ierr;
72779a7d3425SStefano Zampini 
72789a7d3425SStefano Zampini   PetscFunctionBegin;
7279295df10fSStefano Zampini   n = *nio;
72808c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
7281295df10fSStefano Zampini   ierr = PetscMalloc2(n,&alphas,n,&onorms);CHKERRQ(ierr);
728292cccca0SStefano Zampini   ierr = VecNormalize(vecs[0],&norm);CHKERRQ(ierr);
728392cccca0SStefano Zampini   if (norm < PETSC_SMALL) {
7284295df10fSStefano Zampini     onorms[0] = 0.0;
728592cccca0SStefano Zampini     ierr = VecSet(vecs[0],0.0);CHKERRQ(ierr);
7286295df10fSStefano Zampini   } else {
7287295df10fSStefano Zampini     onorms[0] = norm;
728892cccca0SStefano Zampini   }
7289295df10fSStefano Zampini 
72908c0031efSStefano Zampini   for (i=1;i<n;i++) {
72918c0031efSStefano Zampini     ierr = VecMDot(vecs[i],i,vecs,alphas);CHKERRQ(ierr);
72928c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
72938c0031efSStefano Zampini     ierr = VecMAXPY(vecs[i],i,alphas,vecs);CHKERRQ(ierr);
729492cccca0SStefano Zampini     ierr = VecNormalize(vecs[i],&norm);CHKERRQ(ierr);
729592cccca0SStefano Zampini     if (norm < PETSC_SMALL) {
7296295df10fSStefano Zampini       onorms[i] = 0.0;
729792cccca0SStefano Zampini       ierr = VecSet(vecs[i],0.0);CHKERRQ(ierr);
7298295df10fSStefano Zampini     } else {
7299295df10fSStefano Zampini       onorms[i] = norm;
730092cccca0SStefano Zampini     }
73019a7d3425SStefano Zampini   }
7302295df10fSStefano Zampini   /* push nonzero vectors at the beginning */
7303295df10fSStefano Zampini   for (i=0;i<n;i++) {
7304295df10fSStefano Zampini     if (onorms[i] == 0.0) {
7305295df10fSStefano Zampini       for (j=i+1;j<n;j++) {
7306295df10fSStefano Zampini         if (onorms[j] != 0.0) {
7307295df10fSStefano Zampini           ierr = VecCopy(vecs[j],vecs[i]);CHKERRQ(ierr);
7308295df10fSStefano Zampini           onorms[j] = 0.0;
7309295df10fSStefano Zampini         }
7310295df10fSStefano Zampini       }
7311295df10fSStefano Zampini     }
7312295df10fSStefano Zampini   }
7313295df10fSStefano Zampini   for (i=0,*nio=0;i<n;i++) *nio += onorms[i] != 0.0 ? 1 : 0;
7314295df10fSStefano Zampini   ierr = PetscFree2(alphas,onorms);CHKERRQ(ierr);
73159a7d3425SStefano Zampini   PetscFunctionReturn(0);
73169a7d3425SStefano Zampini }
73179a7d3425SStefano Zampini 
7318bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7319e7931f94SStefano Zampini {
732057de7509SStefano Zampini   Mat            A;
7321e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
7322e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
732352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
732452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7325bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
732657de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
732727b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
732827b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
732927b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
733027b6a85dSStefano Zampini   MPI_Comm       subcomm;
733152e5ac9dSStefano Zampini   PetscErrorCode ierr;
7332a57a6d2fSStefano Zampini 
7333e7931f94SStefano Zampini   PetscFunctionBegin;
733457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
733557de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7336fbfcfee5SBarry 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);
733757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
733857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
73396080607fSStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %D",*n_subdomains);
734057de7509SStefano Zampini 
734157de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
7342ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRMPI(ierr);
7343ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRMPI(ierr);
734457de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
734557de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
7346bb360cb4SStefano Zampini   im_active = !!n;
7347820f2d46SBarry Smith   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRMPI(ierr);
734857de7509SStefano Zampini   void_procs = size - active_procs;
734957de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
735057de7509SStefano Zampini   if (void_procs) {
735157de7509SStefano Zampini     PetscInt ncand;
735257de7509SStefano Zampini 
735357de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
735457de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
7355ffc4695bSBarry Smith     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRMPI(ierr);
735657de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
735757de7509SStefano Zampini       if (!procs_candidates[i]) {
735857de7509SStefano Zampini         procs_candidates[ncand++] = i;
735957de7509SStefano Zampini       }
736057de7509SStefano Zampini     }
736157de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
736257de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
736357de7509SStefano Zampini   }
736457de7509SStefano Zampini 
7365bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
73669dddd249SSatish Balay      number of subdomains requested 1 -> send to rank-0 or first candidate in voids  */
7367bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
7368bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
736914f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
737014f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
737114f0bfb9SStefano Zampini     else dest = rank;
737257de7509SStefano Zampini     if (im_active) {
737357de7509SStefano Zampini       issize = 1;
737457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
737514f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
737657de7509SStefano Zampini       } else {
737714f0bfb9SStefano Zampini         isidx = dest;
737857de7509SStefano Zampini       }
737957de7509SStefano Zampini     } else {
738057de7509SStefano Zampini       issize = 0;
738157de7509SStefano Zampini       isidx = -1;
738257de7509SStefano Zampini     }
7383bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
738457de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
7385daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
738657de7509SStefano Zampini     PetscFunctionReturn(0);
738757de7509SStefano Zampini   }
7388c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
7389c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
739027b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7391e7931f94SStefano Zampini 
7392e7931f94SStefano Zampini   /* Get info on mapping */
73933bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7394e7931f94SStefano Zampini 
7395e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
7396785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
7397e7931f94SStefano Zampini   xadj[0] = 0;
7398e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
7399785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
7400785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
7401bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
740227b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
740327b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
740427b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7405e7931f94SStefano Zampini 
740627b6a85dSStefano Zampini   xadj_count = 0;
74072b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
740827b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
740927b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7410d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7411d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7412d023bfaeSStefano Zampini         xadj_count++;
741327b6a85dSStefano Zampini         break;
741427b6a85dSStefano Zampini       }
7415e7931f94SStefano Zampini     }
7416e7931f94SStefano Zampini   }
7417d023bfaeSStefano Zampini   xadj[1] = xadj_count;
741827b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
74193bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
7420e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
7421e7931f94SStefano Zampini 
74223837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
7423e7931f94SStefano Zampini 
742427b6a85dSStefano Zampini   /* Restrict work on active processes only */
742527b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
742627b6a85dSStefano Zampini   if (void_procs) {
742727b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
742827b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
742927b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
743027b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
743127b6a85dSStefano Zampini   } else {
743227b6a85dSStefano Zampini     psubcomm = NULL;
743327b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
743427b6a85dSStefano Zampini   }
743527b6a85dSStefano Zampini 
743627b6a85dSStefano Zampini   v_wgt = NULL;
743727b6a85dSStefano Zampini   if (!color) {
7438e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
7439e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
7440e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7441c8587f34SStefano Zampini   } else {
744252e5ac9dSStefano Zampini     Mat             subdomain_adj;
744352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
744452e5ac9dSStefano Zampini     MatPartitioning partitioner;
744527b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
744652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
744757de7509SStefano Zampini     PetscMPIInt     size;
7448b0c7d250SStefano Zampini     PetscBool       aggregate;
7449b0c7d250SStefano Zampini 
7450ffc4695bSBarry Smith     ierr = MPI_Comm_size(subcomm,&size);CHKERRMPI(ierr);
745127b6a85dSStefano Zampini     if (void_procs) {
745227b6a85dSStefano Zampini       PetscInt prank = rank;
7453785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
7454ffc4695bSBarry Smith       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRMPI(ierr);
7455e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
7456e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
7457c8587f34SStefano Zampini       }
7458e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
745927b6a85dSStefano Zampini     } else {
746027b6a85dSStefano Zampini       oldranks = NULL;
746127b6a85dSStefano Zampini     }
7462b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
746327b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7464b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7465b0c7d250SStefano Zampini       PetscMPIInt nrank;
7466b0c7d250SStefano Zampini       PetscScalar *vals;
7467b0c7d250SStefano Zampini 
7468ffc4695bSBarry Smith       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRMPI(ierr);
7469b0c7d250SStefano Zampini       lrows = 0;
7470b0c7d250SStefano Zampini       if (nrank<redprocs) {
7471b0c7d250SStefano Zampini         lrows = size/redprocs;
7472b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7473b0c7d250SStefano Zampini       }
747427b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
7475b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
7476b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7477b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7478b0c7d250SStefano Zampini       row = nrank;
7479b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7480b0c7d250SStefano Zampini       cols = adjncy;
7481b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
7482b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
7483b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
7484b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7485b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
748652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
748752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
748852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
7489b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
749027b6a85dSStefano Zampini       if (use_vwgt) {
749127b6a85dSStefano Zampini         Vec               v;
749227b6a85dSStefano Zampini         const PetscScalar *array;
749327b6a85dSStefano Zampini         PetscInt          nl;
749427b6a85dSStefano Zampini 
749527b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
7496bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
749727b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
749827b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
749927b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
750027b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
750127b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
750222db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
750327b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
750427b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
750527b6a85dSStefano Zampini       }
7506b0c7d250SStefano Zampini     } else {
750727b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
750827b6a85dSStefano Zampini       if (use_vwgt) {
750927b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
7510bb360cb4SStefano Zampini         v_wgt[0] = n;
751127b6a85dSStefano Zampini       }
7512b0c7d250SStefano Zampini     }
751322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
7514e7931f94SStefano Zampini 
7515e7931f94SStefano Zampini     /* Partition */
751627b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
7517ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH)
7518ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH);CHKERRQ(ierr);
7519ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS)
7520ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS);CHKERRQ(ierr);
7521ce64c636SStefano Zampini #else
7522ce64c636SStefano Zampini     ierr = MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE);CHKERRQ(ierr);
7523ce64c636SStefano Zampini #endif
7524e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
752527b6a85dSStefano Zampini     if (v_wgt) {
7526e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
7527c8587f34SStefano Zampini     }
752857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
752957de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
7530e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
7531e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
753222b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
7533e7931f94SStefano Zampini 
753452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
75356583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
753652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
753752e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
753857de7509SStefano Zampini     if (!aggregate) {
753957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
7540cf9c20a2SJed Brown         if (PetscUnlikelyDebug(!oldranks)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
754157de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
754227b6a85dSStefano Zampini       } else if (oldranks) {
7543b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
754427b6a85dSStefano Zampini       } else {
754527b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
754657de7509SStefano Zampini       }
754728143c3dSStefano Zampini     } else {
75487fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7549b0c7d250SStefano Zampini       PetscMPIInt tag;
7550b0c7d250SStefano Zampini       MPI_Request *reqs;
7551b0c7d250SStefano Zampini 
7552b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
7553b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
7554b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
7555ffc4695bSBarry Smith         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRMPI(ierr);
755628143c3dSStefano Zampini       }
7557ffc4695bSBarry Smith       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRMPI(ierr);
7558ffc4695bSBarry Smith       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
7559b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
756057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
7561cf9c20a2SJed Brown         if (PetscUnlikelyDebug(!oldranks)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
75627fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
756327b6a85dSStefano Zampini       } else if (oldranks) {
75647fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
756527b6a85dSStefano Zampini       } else {
75667fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7567e7931f94SStefano Zampini       }
756857de7509SStefano Zampini     }
756952e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
7570e7931f94SStefano Zampini     /* clean up */
7571e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
757252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
7573e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
7574e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
7575e7931f94SStefano Zampini   }
757627b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
757757de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
7578e7931f94SStefano Zampini 
7579e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7580e7931f94SStefano Zampini   i = 1;
758127b6a85dSStefano Zampini   if (!color) i=0;
758257de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7583e7931f94SStefano Zampini   PetscFunctionReturn(0);
7584e7931f94SStefano Zampini }
7585e7931f94SStefano Zampini 
7586e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7587e7931f94SStefano Zampini 
75881e0482f5SStefano 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[])
7589e7931f94SStefano Zampini {
759070cf5478SStefano Zampini   Mat                    local_mat;
7591e7931f94SStefano Zampini   IS                     is_sends_internal;
75929d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
75931ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
75949d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7595e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7596e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7597e7931f94SStefano Zampini   const PetscInt*        is_indices;
7598e7931f94SStefano Zampini   MatType                new_local_type;
7599e7931f94SStefano Zampini   /* buffers */
7600e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
760128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
76029d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
76031683a169SBarry Smith   PetscScalar            *ptr_vals,*recv_buffer_vals;
76041683a169SBarry Smith   const PetscScalar      *send_buffer_vals;
76051ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7606e7931f94SStefano Zampini   /* MPI */
760728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
760828143c3dSStefano Zampini   PetscSubcomm           subcomm;
7609e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
761028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
761128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
76121ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
76131ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
76141ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7615e7931f94SStefano Zampini   PetscErrorCode         ierr;
7616e7931f94SStefano Zampini 
7617e7931f94SStefano Zampini   PetscFunctionBegin;
761857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7619e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7620fbfcfee5SBarry 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);
762157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
762257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
762357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
762457de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
762557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
76261ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
76271ae86dd6SStefano Zampini   if (nvecs) {
76281ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
76291ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
76301ae86dd6SStefano Zampini   }
763157de7509SStefano Zampini   /* further checks */
7632e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7633e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7634e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7635e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7636e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
763757de7509SStefano Zampini   if (reuse && *mat_n) {
763870cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
763957de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
764070cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
764128143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
764270cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
764370cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
764470cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
764570cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
764670cf5478SStefano Zampini   }
7647e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7648064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(mat,bs,1);
764957de7509SStefano Zampini 
7650e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7651e7931f94SStefano Zampini   if (!is_sends) {
765228143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7653bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7654c8587f34SStefano Zampini   } else {
7655e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7656e7931f94SStefano Zampini     is_sends_internal = is_sends;
7657c8587f34SStefano Zampini   }
7658e7931f94SStefano Zampini 
7659e7931f94SStefano Zampini   /* get comm */
7660a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7661e7931f94SStefano Zampini 
7662e7931f94SStefano Zampini   /* compute number of sends */
7663e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7664e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7665e7931f94SStefano Zampini 
7666e7931f94SStefano Zampini   /* compute number of receives */
7667ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
7668e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&iflags);CHKERRQ(ierr);
7669580bdb30SBarry Smith   ierr = PetscArrayzero(iflags,size);CHKERRQ(ierr);
7670e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7671e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7672e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7673e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7674e7931f94SStefano Zampini 
767528143c3dSStefano Zampini   /* restrict comm if requested */
76760a545947SLisandro Dalcin   subcomm = NULL;
767728143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
767828143c3dSStefano Zampini   if (restrict_comm) {
7679779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7680779c1cceSStefano Zampini 
768128143c3dSStefano Zampini     color = 0;
768253a05cb3SStefano Zampini     if (restrict_full) {
768353a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
768453a05cb3SStefano Zampini     } else {
768553a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
768653a05cb3SStefano Zampini     }
7687820f2d46SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr);
7688e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
768928143c3dSStefano Zampini     /* check if reuse has been requested */
769057de7509SStefano Zampini     if (reuse) {
769128143c3dSStefano Zampini       if (*mat_n) {
769228143c3dSStefano Zampini         PetscMPIInt subcommsize2;
7693ffc4695bSBarry Smith         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRMPI(ierr);
769428143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
769528143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
769628143c3dSStefano Zampini       } else {
769728143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
769828143c3dSStefano Zampini       }
769928143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7700779c1cceSStefano Zampini       PetscMPIInt rank;
7701779c1cceSStefano Zampini 
7702ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
770328143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
770428143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
770528143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7706306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
770728143c3dSStefano Zampini     }
770828143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
770928143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
771028143c3dSStefano Zampini   } else {
771128143c3dSStefano Zampini     comm_n = comm;
771228143c3dSStefano Zampini   }
771328143c3dSStefano Zampini 
7714e7931f94SStefano Zampini   /* prepare send/receive buffers */
7715e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_idxs);CHKERRQ(ierr);
7716580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_idxs,size);CHKERRQ(ierr);
7717e569e4e1SStefano Zampini   ierr = PetscMalloc1(size,&ilengths_vals);CHKERRQ(ierr);
7718580bdb30SBarry Smith   ierr = PetscArrayzero(ilengths_vals,size);CHKERRQ(ierr);
771928143c3dSStefano Zampini   if (nis) {
7720e569e4e1SStefano Zampini     ierr = PetscCalloc1(size,&ilengths_idxs_is);CHKERRQ(ierr);
772128143c3dSStefano Zampini   }
7722e7931f94SStefano Zampini 
772328143c3dSStefano Zampini   /* Get data from local matrices */
77246c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7725e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7726e7931f94SStefano Zampini     /*
7727e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7728e7931f94SStefano Zampini        send_buffer_idxs should contain:
7729e7931f94SStefano Zampini        - MatType_PRIVATE type
7730e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7731e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7732e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7733e7931f94SStefano Zampini     */
77346c4ed002SBarry Smith   else {
77351683a169SBarry Smith     ierr = MatDenseGetArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
77363bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7737854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7738e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7739e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
77403bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7741580bdb30SBarry Smith     ierr = PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i);CHKERRQ(ierr);
77423bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7743e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7744e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7745e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7746e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7747c8587f34SStefano Zampini     }
7748c8587f34SStefano Zampini   }
7749e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
775028143c3dSStefano Zampini   /* additional is (if any) */
775128143c3dSStefano Zampini   if (nis) {
775228143c3dSStefano Zampini     PetscMPIInt psum;
775328143c3dSStefano Zampini     PetscInt j;
775428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
775528143c3dSStefano Zampini       PetscInt plen;
775628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
775728143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
775828143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
775928143c3dSStefano Zampini     }
7760854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
776128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
776228143c3dSStefano Zampini       PetscInt plen;
776328143c3dSStefano Zampini       const PetscInt *is_array_idxs;
776428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
776528143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
776628143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
7767580bdb30SBarry Smith       ierr = PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen);CHKERRQ(ierr);
776828143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
776928143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
777028143c3dSStefano Zampini     }
777128143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
777228143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
777328143c3dSStefano Zampini     }
777428143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
777528143c3dSStefano Zampini   }
77763b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
777728143c3dSStefano Zampini 
7778e7931f94SStefano Zampini   buf_size_idxs = 0;
7779e7931f94SStefano Zampini   buf_size_vals = 0;
778028143c3dSStefano Zampini   buf_size_idxs_is = 0;
77811ae86dd6SStefano Zampini   buf_size_vecs = 0;
7782e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7783e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7784e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
778528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
77861ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7787e7931f94SStefano Zampini   }
7788785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7789785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
779095ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
77911ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7792e7931f94SStefano Zampini 
7793e7931f94SStefano Zampini   /* get new tags for clean communications */
7794e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7795e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
779628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
77971ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7798e7931f94SStefano Zampini 
7799e7931f94SStefano Zampini   /* allocate for requests */
7800785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7801785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
780295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
78031ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7804785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7805785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
780695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
78071ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7808e7931f94SStefano Zampini 
7809e7931f94SStefano Zampini   /* communications */
7810e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7811e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
781228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
78131ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7814e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7815e7931f94SStefano Zampini     source_dest = onodes[i];
7816ffc4695bSBarry Smith     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRMPI(ierr);
7817ffc4695bSBarry Smith     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRMPI(ierr);
7818e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7819e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
782028143c3dSStefano Zampini     if (nis) {
782157de7509SStefano Zampini       source_dest = onodes_is[i];
7822ffc4695bSBarry Smith       ierr = MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]);CHKERRMPI(ierr);
782328143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
782428143c3dSStefano Zampini     }
78251ae86dd6SStefano Zampini     if (nvecs) {
78261ae86dd6SStefano Zampini       source_dest = onodes[i];
7827ffc4695bSBarry Smith       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRMPI(ierr);
78281ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
78291ae86dd6SStefano Zampini     }
7830e7931f94SStefano Zampini   }
7831e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7832e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7833ffc4695bSBarry Smith     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRMPI(ierr);
7834ffc4695bSBarry Smith     ierr = MPI_Isend((PetscScalar*)send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRMPI(ierr);
783528143c3dSStefano Zampini     if (nis) {
7836ffc4695bSBarry Smith       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]);CHKERRMPI(ierr);
783728143c3dSStefano Zampini     }
78381ae86dd6SStefano Zampini     if (nvecs) {
78391ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
7840ffc4695bSBarry Smith       ierr = MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]);CHKERRMPI(ierr);
78411ae86dd6SStefano Zampini     }
7842e7931f94SStefano Zampini   }
7843e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7844e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7845e7931f94SStefano Zampini 
7846e7931f94SStefano Zampini   /* assemble new l2g map */
7847ffc4695bSBarry Smith   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
7848e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78499d30be91SStefano Zampini   new_local_rows = 0;
7850e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
78519d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7852e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7853e7931f94SStefano Zampini   }
78549d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7855e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78569d30be91SStefano Zampini   new_local_rows = 0;
7857e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7858580bdb30SBarry Smith     ierr = PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1));CHKERRQ(ierr);
78599d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7860e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7861e7931f94SStefano Zampini   }
78629d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
78639d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7864e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7865e7931f94SStefano Zampini 
7866e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7867e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7868e7931f94SStefano 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) */
7869e7931f94SStefano Zampini   if (n_recvs) {
787028143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7871e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7872e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7873e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7874e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7875e7931f94SStefano Zampini         break;
7876e7931f94SStefano Zampini       }
7877e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7878e7931f94SStefano Zampini     }
7879e7931f94SStefano Zampini     switch (new_local_type_private) {
788028143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7881e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7882e7931f94SStefano Zampini         bs = 1;
7883e7931f94SStefano Zampini         break;
7884e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7885e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7886e7931f94SStefano Zampini         bs = 1;
7887e7931f94SStefano Zampini         break;
7888e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7889e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7890e7931f94SStefano Zampini         break;
7891e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7892e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7893e7931f94SStefano Zampini         break;
7894e7931f94SStefano Zampini       default:
7895fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7896e7931f94SStefano Zampini     }
7897ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7898ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
789928143c3dSStefano Zampini     bs = 1;
7900e7931f94SStefano Zampini   }
7901e7931f94SStefano Zampini 
790270cf5478SStefano Zampini   /* create MATIS object if needed */
790357de7509SStefano Zampini   if (!reuse) {
7904e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7905e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
790670cf5478SStefano Zampini   } else {
790770cf5478SStefano Zampini     /* it also destroys the local matrices */
790857de7509SStefano Zampini     if (*mat_n) {
790970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
791057de7509SStefano Zampini     } else { /* this is a fake object */
791157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
791257de7509SStefano Zampini     }
791370cf5478SStefano Zampini   }
791470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7915e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
79169d30be91SStefano Zampini 
7917ffc4695bSBarry Smith   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
79189d30be91SStefano Zampini 
79199d30be91SStefano Zampini   /* Global to local map of received indices */
79209d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
79219d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
79229d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
79239d30be91SStefano Zampini 
79249d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
79259d30be91SStefano Zampini   buf_size_idxs = 0;
79269d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
79279d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
79289d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
79299d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
79309d30be91SStefano Zampini   }
79319d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
79329d30be91SStefano Zampini 
79339d30be91SStefano Zampini   /* set preallocation */
79349d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
79359d30be91SStefano Zampini   if (!newisdense) {
79360a545947SLisandro Dalcin     PetscInt *new_local_nnz=NULL;
79379d30be91SStefano Zampini 
79389d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
79399d30be91SStefano Zampini     if (n_recvs) {
79409d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
79419d30be91SStefano Zampini     }
79429d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
79439d30be91SStefano Zampini       PetscInt j;
79449d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
79459d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
79469d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
79479d30be91SStefano Zampini         }
79489d30be91SStefano Zampini       } else {
79499d30be91SStefano Zampini         /* TODO */
79509d30be91SStefano Zampini       }
79519d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
79529d30be91SStefano Zampini     }
79539d30be91SStefano Zampini     if (new_local_nnz) {
79549d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
79559d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
79569d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
79579d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
79589d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
79599d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
79609d30be91SStefano Zampini     } else {
79619d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
79629d30be91SStefano Zampini     }
79639d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
79649d30be91SStefano Zampini   } else {
79659d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
79669d30be91SStefano Zampini   }
7967e7931f94SStefano Zampini 
7968e7931f94SStefano Zampini   /* set values */
7969e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
79709d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7971e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7972e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7973e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
79749d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7975e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7976e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7977e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
797828143c3dSStefano Zampini     } else {
797928143c3dSStefano Zampini       /* TODO */
7980e7931f94SStefano Zampini     }
7981e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7982e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7983e7931f94SStefano Zampini   }
7984e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7985e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79863b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
798770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
798870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79899d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7990e7931f94SStefano Zampini 
7991dfd14d43SStefano Zampini #if 0
799228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7993e7931f94SStefano Zampini     Vec       lvec,rvec;
7994e7931f94SStefano Zampini     PetscReal infty_error;
7995e7931f94SStefano Zampini 
79962a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7997e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7998e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7999e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
800070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
8001e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
80021e1ea65dSPierre Jolivet     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);CHKERRQ(ierr);
8003e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
8004e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
8005e7931f94SStefano Zampini   }
800628143c3dSStefano Zampini #endif
8007e7931f94SStefano Zampini 
800828143c3dSStefano Zampini   /* assemble new additional is (if any) */
800928143c3dSStefano Zampini   if (nis) {
801028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
801128143c3dSStefano Zampini 
8012ffc4695bSBarry Smith     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
8013854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
801428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
801528143c3dSStefano Zampini     psum = 0;
801628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
801728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
801828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
801928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
802028143c3dSStefano Zampini         psum += plen;
802128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
802228143c3dSStefano Zampini       }
802328143c3dSStefano Zampini     }
8024854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
8025854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
802628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
802728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
802828143c3dSStefano Zampini     }
8029580bdb30SBarry Smith     ierr = PetscArrayzero(count_is,nis);CHKERRQ(ierr);
803028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
803128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
803228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
803328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
8034580bdb30SBarry Smith         ierr = PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen);CHKERRQ(ierr);
803528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
803628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
803728143c3dSStefano Zampini       }
803828143c3dSStefano Zampini     }
803928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
804028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
8041c3b366b1Sprj-       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);
804228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
804328143c3dSStefano Zampini     }
804428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
804528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
804628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
804728143c3dSStefano Zampini   }
8048e7931f94SStefano Zampini   /* free workspace */
804928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
8050ffc4695bSBarry Smith   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
8051e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
8052ffc4695bSBarry Smith   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
8053e7931f94SStefano Zampini   if (isdense) {
8054e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
80551683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(local_mat,&send_buffer_vals);CHKERRQ(ierr);
80563b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
8057e7931f94SStefano Zampini   } else {
8058e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
8059e7931f94SStefano Zampini   }
806028143c3dSStefano Zampini   if (nis) {
8061ffc4695bSBarry Smith     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
806228143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
806328143c3dSStefano Zampini   }
80641ae86dd6SStefano Zampini 
80651ae86dd6SStefano Zampini   if (nvecs) {
8066ffc4695bSBarry Smith     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
8067ffc4695bSBarry Smith     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);
80681ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80691ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
80701ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
80711ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
80721ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
80731ae86dd6SStefano Zampini     /* set values */
80741ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
80751ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
80761ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80771ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
80781ae86dd6SStefano Zampini       PetscInt j;
80791ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
80801ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
80811ae86dd6SStefano Zampini       }
80821ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
80831ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
80841ae86dd6SStefano Zampini     }
80851ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
80861ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
80871ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
80881ae86dd6SStefano Zampini   }
80891ae86dd6SStefano Zampini 
80901ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
80911ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
8092e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
8093e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
80941ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
809528143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
8096e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
8097e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
80981ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
809928143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
8100e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
8101e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
8102e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
8103e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
8104e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
810528143c3dSStefano Zampini   if (nis) {
810628143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
810728143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
810828143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
810928143c3dSStefano Zampini   }
811028143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
811128143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
811228143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
811328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
811428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
811528143c3dSStefano Zampini     }
81161ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
81171ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
81181ae86dd6SStefano Zampini     }
811953a05cb3SStefano Zampini     *mat_n = NULL;
812028143c3dSStefano Zampini   }
8121e7931f94SStefano Zampini   PetscFunctionReturn(0);
8122e7931f94SStefano Zampini }
8123a57a6d2fSStefano Zampini 
812412edc857SStefano Zampini /* temporary hack into ksp private data structure */
8125af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
812612edc857SStefano Zampini 
8127c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
8128c8587f34SStefano Zampini {
8129c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
8130c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
813120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
81321ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
81331e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
81349881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
813520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
81364f819b78SStefano Zampini   IS                     coarse_is,*isarray,corners;
81376e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
813830368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
8139e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
8140f9eb5b7dSStefano Zampini   PC                     pc_temp;
8141c8587f34SStefano Zampini   PCType                 coarse_pc_type;
8142c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
8143f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
81447274672aSStefano Zampini   PetscBool              coarse_reuse;
81451e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
814668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
814722bc73bbSStefano Zampini   PetscScalar            *array;
814857de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
814957de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
8150e569e4e1SStefano Zampini   PetscMPIInt            size;
81519881197aSStefano Zampini   PetscErrorCode         ierr;
8152fdc09c96SStefano Zampini 
8153c8587f34SStefano Zampini   PetscFunctionBegin;
815443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8155c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
815668457ee5SStefano 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 */
8157fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
81585a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
81597de4f681Sstefano_zampini 
81607de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
8161fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
8162f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
8163f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
8164f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
8165fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
816651bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
816751bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
8168727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
8169fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
8170fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
8171fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
8172f4ddd8eeSStefano Zampini       }
8173fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
8174fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
8175f4ddd8eeSStefano Zampini     }
817670cf5478SStefano Zampini     /* reset any subassembling information */
817757de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
817870cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
817957de7509SStefano Zampini     }
81806e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
8181fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
8182f4ddd8eeSStefano Zampini   }
818357de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
818457de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
818557de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
818657de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
818718a45a71SStefano Zampini   } else {
818857de7509SStefano Zampini     coarse_mat = NULL;
818957de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
81906e683305SStefano Zampini   }
8191e7931f94SStefano Zampini 
8192abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
8193abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
8194abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
8195abbbba34SStefano Zampini 
8196abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
81974f819b78SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense);CHKERRQ(ierr);
8198e176bc59SStefano 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);
81996e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
82006e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
82016e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8202abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
8203abbbba34SStefano Zampini 
820457de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
820557de7509SStefano Zampini   im_active = !!(pcis->n);
8206820f2d46SBarry Smith   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
820757de7509SStefano Zampini 
820814f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
820928d58a37SPierre Jolivet   /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */
821057de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
8211ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
821257de7509SStefano Zampini   coarse_mat_is        = NULL;
821357de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
821457de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
8215e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
8216ce64c636SStefano Zampini   if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size;
821757de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
8218e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
821957de7509SStefano Zampini   if (multilevel_requested) {
822057de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
822157de7509SStefano Zampini     restr      = PETSC_FALSE;
822257de7509SStefano Zampini     full_restr = PETSC_FALSE;
822357de7509SStefano Zampini   } else {
8224e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
822557de7509SStefano Zampini     restr      = PETSC_TRUE;
822657de7509SStefano Zampini     full_restr = PETSC_TRUE;
822757de7509SStefano Zampini   }
8228e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
822957de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
823057de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
8231a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
8232bb360cb4SStefano Zampini       if (multilevel_requested) {
8233bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8234bb360cb4SStefano Zampini       } else {
8235bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
8236bb360cb4SStefano Zampini       }
8237a198735bSStefano Zampini     } else {
82387de4f681Sstefano_zampini       PetscMPIInt rank;
823928d58a37SPierre Jolivet 
8240ffc4695bSBarry Smith       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr);
8241e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
8242a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
8243a198735bSStefano Zampini     }
824457de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
824557de7509SStefano Zampini     PetscInt    psum;
824657de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
824757de7509SStefano Zampini     else psum = 0;
8248820f2d46SBarry Smith     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
8249075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
825057de7509SStefano Zampini   }
825157de7509SStefano Zampini   /* determine if we can go multilevel */
825257de7509SStefano Zampini   if (multilevel_requested) {
825357de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
825457de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
825557de7509SStefano Zampini   }
825657de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
825757de7509SStefano Zampini 
8258e4d548c7SStefano Zampini   /* dump subassembling pattern */
8259e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
8260e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
8261e4d548c7SStefano Zampini   }
82626e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
82631e0482f5SStefano Zampini   nedcfield = -1;
82644f819b78SStefano Zampini   corners = NULL;
82658966356dSPierre Jolivet   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */
82666e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
82676e683305SStefano Zampini     const PetscInt         *idxs;
82686e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
82696e683305SStefano Zampini 
82706e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
82710be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
82726e683305SStefano Zampini     /* allocate space for temporary storage */
8273854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
8274854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
82756e683305SStefano Zampini     /* allocate for IS array */
82766e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
82771e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
82781e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
82791e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
82801e0482f5SStefano Zampini       } else {
82811e0482f5SStefano Zampini         nedcfield = 0;
82826080607fSStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%D)",nisdofs);
82831e0482f5SStefano Zampini         nisdofs = 1;
82841e0482f5SStefano Zampini       }
82851e0482f5SStefano Zampini     }
82866e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
828727b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
828830368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
8289854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
82906e683305SStefano Zampini     /* dofs splitting */
82916e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
82926e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
82931e0482f5SStefano Zampini       if (nedcfield != i) {
82946e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
82956e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
82966e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
82976e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
82981e0482f5SStefano Zampini       } else {
82991e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
83001e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
83011e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
83026080607fSStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %D != %D",tsize,nout);
83031e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
83041e0482f5SStefano Zampini       }
83056e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
830630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
83076e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
83086e683305SStefano Zampini     }
83096e683305SStefano Zampini     /* neumann boundaries */
83106e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
83116e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
83126e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
83136e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
83146e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
83156e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
83166e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
831730368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
83186e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
83196e683305SStefano Zampini     }
83204f819b78SStefano Zampini     /* coordinates */
83214f819b78SStefano Zampini     if (pcbddc->corner_selected) {
83224f819b78SStefano Zampini       ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
83234f819b78SStefano Zampini       ierr = ISGetLocalSize(corners,&tsize);CHKERRQ(ierr);
83244f819b78SStefano Zampini       ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
83254f819b78SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
83264f819b78SStefano Zampini       if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %D != %D",tsize,nout);
83274f819b78SStefano Zampini       ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
83284f819b78SStefano Zampini       ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners);CHKERRQ(ierr);
83294f819b78SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
83304f819b78SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners);CHKERRQ(ierr);
83314f819b78SStefano Zampini     }
83326e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
83336e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
83346e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
83356e683305SStefano Zampini   } else {
83366e683305SStefano Zampini     nis = 0;
83376e683305SStefano Zampini     nisdofs = 0;
83386e683305SStefano Zampini     nisneu = 0;
833930368db7SStefano Zampini     nisvert = 0;
83406e683305SStefano Zampini     isarray = NULL;
83416e683305SStefano Zampini   }
83426e683305SStefano Zampini   /* destroy no longer needed map */
83436e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
83446e683305SStefano Zampini 
834557de7509SStefano Zampini   /* subassemble */
834657de7509SStefano Zampini   if (multilevel_allowed) {
83471ae86dd6SStefano Zampini     Vec       vp[1];
83481ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
834957de7509SStefano Zampini     PetscBool reuse,reuser;
83501ae86dd6SStefano Zampini 
835157de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
835257de7509SStefano Zampini     else reuse = PETSC_FALSE;
8353820f2d46SBarry Smith     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
83541ae86dd6SStefano Zampini     vp[0] = NULL;
83551ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
83561ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
83571ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
83581ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
83591ae86dd6SStefano Zampini       nvecs = 1;
83601ae86dd6SStefano Zampini 
83611ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8362a198735bSStefano Zampini         Mat      B,loc_divudotp;
83631ae86dd6SStefano Zampini         Vec      v,p;
83641ae86dd6SStefano Zampini         IS       dummy;
83651ae86dd6SStefano Zampini         PetscInt np;
83661ae86dd6SStefano Zampini 
8367a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
8368a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
83691ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
83707dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
83711ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
83721ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
83731ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
83741ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
83751ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
83761ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
83771ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
83781ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
83791ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
8380*ab2d12f3SJunchao Zhang         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
83811ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
83821ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
838374e2c79eSStefano Zampini       }
83841ae86dd6SStefano Zampini     }
83851ae86dd6SStefano Zampini     if (reuser) {
83861e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
838774e2c79eSStefano Zampini     } else {
83881e0482f5SStefano 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);
83891ae86dd6SStefano Zampini     }
83901ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
83911683a169SBarry Smith       PetscScalar       *arraym;
83921683a169SBarry Smith       const PetscScalar *arrayv;
83931ae86dd6SStefano Zampini       PetscInt          nl;
83941ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
83951ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
83961ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
83971683a169SBarry Smith       ierr = VecGetArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
8398580bdb30SBarry Smith       ierr = PetscArraycpy(arraym,arrayv,nl);CHKERRQ(ierr);
83991683a169SBarry Smith       ierr = VecRestoreArrayRead(vp[0],&arrayv);CHKERRQ(ierr);
84001ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
84011ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
8402a198735bSStefano Zampini     } else {
8403a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
84041ae86dd6SStefano Zampini     }
84051ae86dd6SStefano Zampini   } else {
84061e0482f5SStefano 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);
84076e683305SStefano Zampini   }
840857de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
840957de7509SStefano Zampini     if (!multilevel_allowed) {
8410487b449aSStefano Zampini       ierr = MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
84116e683305SStefano Zampini     } else {
841257de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
841357de7509SStefano Zampini       if (coarse_mat_is) {
841457de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
841557de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
841657de7509SStefano Zampini         coarse_mat = coarse_mat_is;
841757de7509SStefano Zampini       }
8418779c1cceSStefano Zampini     }
8419779c1cceSStefano Zampini   }
842057de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
842157de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
84226e683305SStefano Zampini 
84236e683305SStefano Zampini   /* create local to global scatters for coarse problem */
842468457ee5SStefano Zampini   if (compute_vecs) {
84256e683305SStefano Zampini     PetscInt lrows;
84266e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
842757de7509SStefano Zampini     if (coarse_mat) {
842857de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
84296e683305SStefano Zampini     } else {
84306e683305SStefano Zampini       lrows = 0;
84316e683305SStefano Zampini     }
84326e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
84336e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
843489535278SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD);CHKERRQ(ierr);
84356e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
84369448b7f1SJunchao Zhang     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
84376e683305SStefano Zampini   }
84386e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
8439c8587f34SStefano Zampini 
8440f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8441f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8442f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8443f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8444f9eb5b7dSStefano Zampini   } else {
8445f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8446f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8447c8587f34SStefano Zampini   }
8448c8587f34SStefano Zampini 
84496e683305SStefano Zampini   /* print some info if requested */
84506e683305SStefano Zampini   if (pcbddc->dbg_flag) {
84516e683305SStefano Zampini     if (!multilevel_allowed) {
84526e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
84536e683305SStefano Zampini       if (multilevel_requested) {
84546080607fSStefano 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);
84556e683305SStefano Zampini       } else if (pcbddc->max_levels) {
84566080607fSStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%D)\n",pcbddc->max_levels);CHKERRQ(ierr);
84576e683305SStefano Zampini       }
84586e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
84596e683305SStefano Zampini     }
84606e683305SStefano Zampini   }
84616e683305SStefano Zampini 
84621e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
84631e0482f5SStefano Zampini   coarseG = NULL;
84641e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
84651e0482f5SStefano Zampini     MPI_Comm ccomm;
84661e0482f5SStefano Zampini     if (coarse_mat) {
84671e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
84681e0482f5SStefano Zampini     } else {
84691e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
84701e0482f5SStefano Zampini     }
84711e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
84721e0482f5SStefano Zampini   }
84731e0482f5SStefano Zampini 
8474f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
847557de7509SStefano Zampini   if (coarse_mat) {
847628d58a37SPierre Jolivet     PetscBool   isredundant,isbddc,force,valid;
84776a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
84787274672aSStefano Zampini 
84796e683305SStefano Zampini     if (pcbddc->dbg_flag) {
848057de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
84816e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
84826e683305SStefano Zampini     }
8483f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8484312be037SStefano Zampini       char   prefix[256],str_level[16];
8485e604994aSStefano Zampini       size_t len;
84861e0482f5SStefano Zampini 
848757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
8488422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
8489c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8490f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
849157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8492c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
84936e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
8494c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
84951e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
8496c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8497e604994aSStefano Zampini       /* prefix */
8498e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
8499e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
8500e604994aSStefano Zampini       if (!pcbddc->current_level) {
8501a126751eSBarry Smith         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix));CHKERRQ(ierr);
8502a126751eSBarry Smith         ierr = PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix));CHKERRQ(ierr);
8503c8587f34SStefano Zampini       } else {
8504e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
8505312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8506312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8507a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
850834d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
850935529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
8510a126751eSBarry Smith         ierr = PetscStrlcat(prefix,str_level,sizeof(prefix));CHKERRQ(ierr);
8511e604994aSStefano Zampini       }
8512e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
85133e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
85143e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
85153e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
85163e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
8517f9eb5b7dSStefano Zampini       /* allow user customization */
8518f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
8519e569e4e1SStefano Zampini       /* get some info after set from options */
8520e569e4e1SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
852128d58a37SPierre Jolivet       /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
852228d58a37SPierre Jolivet       force = PETSC_FALSE;
852328d58a37SPierre Jolivet       ierr = PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL);CHKERRQ(ierr);
852428d58a37SPierre Jolivet       ierr = PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"");CHKERRQ(ierr);
8525e569e4e1SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
852628d58a37SPierre Jolivet       if (multilevel_allowed && !force && !valid) {
8527e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
8528e569e4e1SStefano Zampini         ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8529e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
8530e569e4e1SStefano Zampini         ierr   = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
8531e569e4e1SStefano Zampini         ierr   = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
85324f819b78SStefano Zampini         if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */
85334f819b78SStefano Zampini           ierr = PetscObjectOptionsBegin((PetscObject)pc_temp);CHKERRQ(ierr);
85344f819b78SStefano Zampini           ierr = (*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp);CHKERRQ(ierr);
85354f819b78SStefano Zampini           ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp);CHKERRQ(ierr);
85364f819b78SStefano Zampini           ierr = PetscOptionsEnd();CHKERRQ(ierr);
85374f819b78SStefano Zampini           pc_temp->setfromoptionscalled++;
85384f819b78SStefano Zampini         }
8539e569e4e1SStefano Zampini       }
85403e3c6dadSStefano Zampini     }
85413e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
854251bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
85433e3c6dadSStefano Zampini     if (nisdofs) {
85443e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
85453e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
85463e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
85473e3c6dadSStefano Zampini       }
85483e3c6dadSStefano Zampini     }
85493e3c6dadSStefano Zampini     if (nisneu) {
85503e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
85513e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
8552312be037SStefano Zampini     }
855330368db7SStefano Zampini     if (nisvert) {
855430368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
855530368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
855630368db7SStefano Zampini     }
85571e0482f5SStefano Zampini     if (coarseG) {
85581e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
85591e0482f5SStefano Zampini     }
8560f9eb5b7dSStefano Zampini 
8561f9eb5b7dSStefano Zampini     /* get some info after set from options */
8562f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
85634f819b78SStefano Zampini 
8564b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8565b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
8566f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
8567f9eb5b7dSStefano Zampini     }
856828d58a37SPierre Jolivet     /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
856928d58a37SPierre Jolivet     force = PETSC_FALSE;
857028d58a37SPierre Jolivet     ierr = PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL);CHKERRQ(ierr);
857128d58a37SPierre Jolivet     ierr = PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"");CHKERRQ(ierr);
857228d58a37SPierre Jolivet     if (multilevel_requested && multilevel_allowed && !valid && !force) {
8573b76f3995Sstefano_zampini       ierr = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
8574b76f3995Sstefano_zampini     }
85757274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
85764f3a063dSStefano Zampini     if (isredundant) {
85774f3a063dSStefano Zampini       KSP inner_ksp;
85784f3a063dSStefano Zampini       PC  inner_pc;
85799326c5c6Sstefano_zampini 
85804f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
85814f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
85824f3a063dSStefano Zampini     }
8583f9eb5b7dSStefano Zampini 
858457de7509SStefano Zampini     /* parameters which miss an API */
85857274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
858657de7509SStefano Zampini     if (isbddc) {
8587720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
85887274672aSStefano Zampini 
8589720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
859057de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8591e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
859227b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
859327b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8594a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8595a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8596a198735bSStefano Zampini         IS                     row,col;
8597a198735bSStefano Zampini         const PetscInt         *gidxs;
8598a198735bSStefano Zampini         PetscInt               n,st,M,N;
8599a198735bSStefano Zampini 
8600a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
8601ffc4695bSBarry Smith         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRMPI(ierr);
8602a198735bSStefano Zampini         st   = st-n;
8603a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
8604a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
8605a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
8606a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8607a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
8608a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
8609a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8610a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8611a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8612a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8613a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8614a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8615a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8616a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8617a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8618a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8619a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8620a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8621a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8622a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
86238ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8624a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8625720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8626bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8627720d30f9SStefano Zampini       }
8628d4d8cf7bSStefano Zampini     }
86299881197aSStefano Zampini 
86303301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
86315a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
86323301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
86333301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
86343301b35fSStefano Zampini     }
86353301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
86363301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
86373301b35fSStefano Zampini     }
86383301b35fSStefano Zampini     if (pc->pmat->spd_set) {
86393301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
86403301b35fSStefano Zampini     }
864127b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
864227b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
864327b6a85dSStefano Zampini     }
86446e683305SStefano Zampini     /* set operators */
864504fe1396SStefano Zampini     ierr = MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view");CHKERRQ(ierr);
86463007b4efSStefano Zampini     ierr = MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix);CHKERRQ(ierr);
86475f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
86486e683305SStefano Zampini     if (pcbddc->dbg_flag) {
86496e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
86506e683305SStefano Zampini     }
86516e683305SStefano Zampini   }
86521e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
86536e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8654b1ecc7b1SStefano Zampini #if 0
8655b9b85e73SStefano Zampini   {
8656b9b85e73SStefano Zampini     PetscViewer viewer;
8657b9b85e73SStefano Zampini     char filename[256];
8658b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8659b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
86606a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8661b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8662f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8663b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8664b9b85e73SStefano Zampini   }
8665b9b85e73SStefano Zampini #endif
8666f9eb5b7dSStefano Zampini 
86674f819b78SStefano Zampini   if (corners) {
86684f819b78SStefano Zampini     Vec            gv;
86694f819b78SStefano Zampini     IS             is;
86704f819b78SStefano Zampini     const PetscInt *idxs;
86714f819b78SStefano Zampini     PetscInt       i,d,N,n,cdim = pcbddc->mat_graph->cdim;
86724f819b78SStefano Zampini     PetscScalar    *coords;
86734f819b78SStefano Zampini 
86744f819b78SStefano Zampini     if (!pcbddc->mat_graph->cloc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates");
86754f819b78SStefano Zampini     ierr = VecGetSize(pcbddc->coarse_vec,&N);CHKERRQ(ierr);
86764f819b78SStefano Zampini     ierr = VecGetLocalSize(pcbddc->coarse_vec,&n);CHKERRQ(ierr);
86774f819b78SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv);CHKERRQ(ierr);
86784f819b78SStefano Zampini     ierr = VecSetBlockSize(gv,cdim);CHKERRQ(ierr);
86794f819b78SStefano Zampini     ierr = VecSetSizes(gv,n*cdim,N*cdim);CHKERRQ(ierr);
86804f819b78SStefano Zampini     ierr = VecSetType(gv,VECSTANDARD);CHKERRQ(ierr);
86814f819b78SStefano Zampini     ierr = VecSetFromOptions(gv);CHKERRQ(ierr);
86824f819b78SStefano Zampini     ierr = VecSet(gv,PETSC_MAX_REAL);CHKERRQ(ierr); /* we only propagate coordinates from vertices constraints */
86834f819b78SStefano Zampini 
86844f819b78SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
86854f819b78SStefano Zampini     ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
86864f819b78SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
86874f819b78SStefano Zampini     ierr = PetscMalloc1(n*cdim,&coords);CHKERRQ(ierr);
86884f819b78SStefano Zampini     for (i=0;i<n;i++) {
86894f819b78SStefano Zampini       for (d=0;d<cdim;d++) {
86904f819b78SStefano Zampini         coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d];
86914f819b78SStefano Zampini       }
86924f819b78SStefano Zampini     }
86934f819b78SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
86944f819b78SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is);CHKERRQ(ierr);
86954f819b78SStefano Zampini 
86964f819b78SStefano Zampini     ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
86974f819b78SStefano Zampini     ierr = ISGetIndices(corners,&idxs);CHKERRQ(ierr);
86984f819b78SStefano Zampini     ierr = VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES);CHKERRQ(ierr);
86994f819b78SStefano Zampini     ierr = ISRestoreIndices(corners,&idxs);CHKERRQ(ierr);
87004f819b78SStefano Zampini     ierr = PetscFree(coords);CHKERRQ(ierr);
87014f819b78SStefano Zampini     ierr = VecAssemblyBegin(gv);CHKERRQ(ierr);
87024f819b78SStefano Zampini     ierr = VecAssemblyEnd(gv);CHKERRQ(ierr);
87034f819b78SStefano Zampini     ierr = VecGetArray(gv,&coords);CHKERRQ(ierr);
87044f819b78SStefano Zampini     if (pcbddc->coarse_ksp) {
87054f819b78SStefano Zampini       PC        coarse_pc;
87064f819b78SStefano Zampini       PetscBool isbddc;
87074f819b78SStefano Zampini 
87084f819b78SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
87094f819b78SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
87104f819b78SStefano Zampini       if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */
87114f819b78SStefano Zampini         PetscReal *realcoords;
87124f819b78SStefano Zampini 
87134f819b78SStefano Zampini         ierr = VecGetLocalSize(gv,&n);CHKERRQ(ierr);
87144f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
87154f819b78SStefano Zampini         ierr = PetscMalloc1(n,&realcoords);CHKERRQ(ierr);
87164f819b78SStefano Zampini         for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]);
87174f819b78SStefano Zampini #else
87184f819b78SStefano Zampini         realcoords = coords;
87194f819b78SStefano Zampini #endif
87204f819b78SStefano Zampini         ierr = PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords);CHKERRQ(ierr);
87214f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
87224f819b78SStefano Zampini         ierr = PetscFree(realcoords);CHKERRQ(ierr);
87234f819b78SStefano Zampini #endif
87244f819b78SStefano Zampini       }
87254f819b78SStefano Zampini     }
87264f819b78SStefano Zampini     ierr = VecRestoreArray(gv,&coords);CHKERRQ(ierr);
87274f819b78SStefano Zampini     ierr = VecDestroy(&gv);CHKERRQ(ierr);
87284f819b78SStefano Zampini   }
87294f819b78SStefano Zampini   ierr = ISDestroy(&corners);CHKERRQ(ierr);
87304f819b78SStefano Zampini 
873198a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
873298a51de6SStefano Zampini     Vec crhs,csol;
873304708bb6SStefano Zampini 
8734f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8735f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8736f347579bSStefano Zampini     if (!csol) {
87372a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8738f9eb5b7dSStefano Zampini     }
8739f347579bSStefano Zampini     if (!crhs) {
87402a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8741f347579bSStefano Zampini     }
8742b0f5fe93SStefano Zampini   }
87431ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8744b0f5fe93SStefano Zampini 
8745b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8746b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8747b0f5fe93SStefano Zampini 
8748b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
87494f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
87504f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
87514f1b2e48SStefano Zampini     }
8752b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8753b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8754b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8755b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8756b0f5fe93SStefano Zampini     if (coarse_mat) {
8757b0f5fe93SStefano Zampini       Vec         nullv;
8758b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8759b0f5fe93SStefano Zampini       PetscInt    nl;
8760b0f5fe93SStefano Zampini 
8761b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8762b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8763b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8764b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8765580bdb30SBarry Smith       ierr = PetscArraycpy(array2,array,nl);CHKERRQ(ierr);
8766b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8767b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8768b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8769b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8770b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8771b0f5fe93SStefano Zampini     }
8772b0f5fe93SStefano Zampini   }
877343371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8774b0f5fe93SStefano Zampini 
877543371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8776b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8777b0f5fe93SStefano Zampini     PetscBool ispreonly;
8778b0f5fe93SStefano Zampini 
8779b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8780b0f5fe93SStefano Zampini       PetscBool isnull;
8781b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8782bef83e63SStefano Zampini       if (isnull) {
8783b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8784b0f5fe93SStefano Zampini       }
8785bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8786b0f5fe93SStefano Zampini     }
8787b0f5fe93SStefano Zampini     /* setup coarse ksp */
8788b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8789cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8790cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
87916e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) {
8792c8587f34SStefano Zampini       KSP       check_ksp;
87932b510759SStefano Zampini       KSPType   check_ksp_type;
8794c8587f34SStefano Zampini       PC        check_pc;
87956e683305SStefano Zampini       Vec       check_vec,coarse_vec;
87966a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
87972b510759SStefano Zampini       PetscInt  its;
87986e683305SStefano Zampini       PetscBool compute_eigs;
87996e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
88006e683305SStefano Zampini       PetscInt  neigs;
88018e185a42SStefano Zampini       const char *prefix;
8802c8587f34SStefano Zampini 
88032b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
88046e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
880515579a77SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0);CHKERRQ(ierr);
8806399ffe99SStefano Zampini       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
880723ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8808f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8809e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8810e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8811e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
88122b510759SStefano Zampini       if (ispreonly) {
88132b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
88146e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
88152b510759SStefano Zampini       } else {
8816cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
88176e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8818c8587f34SStefano Zampini       }
8819c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
88206e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
88216e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
88226e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8823a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8824a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8825a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8826a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8827c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8828c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8829c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8830c8587f34SStefano Zampini       /* create random vec */
88312701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8832c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
88336e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8834c8587f34SStefano Zampini       /* solve coarse problem */
88356e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8836c0decd05SBarry Smith       ierr = KSPCheckSolve(check_ksp,pc,coarse_vec);CHKERRQ(ierr);
8837cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
88386e683305SStefano Zampini       if (compute_eigs) {
8839854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8840854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
88416e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
88421ae86dd6SStefano Zampini         if (neigs) {
88436e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
88446e683305SStefano Zampini           lambda_min = eigs_r[0];
88456e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
88462701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
88472701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8848cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8849cbcc2c2aSStefano Zampini             }
8850c8587f34SStefano Zampini           }
8851c8587f34SStefano Zampini         }
88521ae86dd6SStefano Zampini       }
8853cbcc2c2aSStefano Zampini 
8854c8587f34SStefano Zampini       /* check coarse problem residual error */
88556e683305SStefano Zampini       if (pcbddc->dbg_flag) {
88566e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
88576e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
88586e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8859c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
88606e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
88616e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8862779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
88636e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
88646e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
88656e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
88666e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8867b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8868b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8869b0f5fe93SStefano Zampini         }
88706e683305SStefano Zampini         if (compute_eigs) {
88716e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8872b03ebc13SStefano Zampini           KSPConvergedReason reason;
8873deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8874c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8875b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
88766e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8877b03ebc13SStefano 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);
88786e683305SStefano Zampini           for (i=0;i<neigs;i++) {
88796e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8880c8587f34SStefano Zampini           }
88816e683305SStefano Zampini         }
88826e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
88836e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
88846e683305SStefano Zampini       }
8885e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
88862701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8887c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
88886e683305SStefano Zampini       if (compute_eigs) {
88896e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
88906e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8891c8587f34SStefano Zampini       }
88926e683305SStefano Zampini     }
88936e683305SStefano Zampini   }
8894bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8895cbcc2c2aSStefano Zampini   /* print additional info */
8896cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
88976e683305SStefano Zampini     /* waits until all processes reaches this point */
88986e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
88996080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %D\n",pcbddc->current_level);CHKERRQ(ierr);
8900cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8901cbcc2c2aSStefano Zampini   }
8902cbcc2c2aSStefano Zampini 
89032b510759SStefano Zampini   /* free memory */
8904fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
890543371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
8906c8587f34SStefano Zampini   PetscFunctionReturn(0);
8907c8587f34SStefano Zampini }
8908674ae819SStefano Zampini 
8909f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8910f34684f1SStefano Zampini {
8911f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8912f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8913f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8914dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8915dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
891673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8917dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8918f34684f1SStefano Zampini   PetscErrorCode ierr;
8919f34684f1SStefano Zampini 
8920f34684f1SStefano Zampini   PetscFunctionBegin;
8921f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
89226c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8923dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
89243bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8925dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8926dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
89276583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8928dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8929dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8930dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
89316c4ed002SBarry 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);
8932dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8933dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8934580bdb30SBarry Smith   ierr = PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size);CHKERRQ(ierr);
8935dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8936dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8937f34684f1SStefano Zampini 
8938f34684f1SStefano Zampini   /* check numbering */
8939f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8940019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8941dc456d91SStefano Zampini     PetscInt    i;
8942b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8943f34684f1SStefano Zampini 
8944f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8945f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8946f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
89471575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8948019a44ceSStefano Zampini     /* counter */
8949019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8950019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8951019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8952019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8953019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8954019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8955f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8956f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8957727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8958f34684f1SStefano Zampini     }
8959f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8960f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8961f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8962e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8963e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8964e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8965e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8966f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8967019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8968f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8969019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
89702c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
897175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8972b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
89732c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
89746080607fSStefano 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);
8975f34684f1SStefano Zampini       }
8976f34684f1SStefano Zampini     }
8977019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8978820f2d46SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
8979f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8980f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8981f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8982f34684f1SStefano Zampini     }
8983f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8984f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8985e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8986e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8987f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
89886080607fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %D (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8989b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8990ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8991ca8b9ea9SStefano Zampini 
8992ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
89933bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8994f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8995f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8996f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8997f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
89986080607fSStefano 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);
8999f34684f1SStefano Zampini       }
9000f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
9001ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
9002f34684f1SStefano Zampini     }
9003f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
90041575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9005302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
9006f34684f1SStefano Zampini   }
90076080607fSStefano Zampini 
9008f34684f1SStefano Zampini   /* get back data */
9009f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
9010f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
9011674ae819SStefano Zampini   PetscFunctionReturn(0);
9012674ae819SStefano Zampini }
9013674ae819SStefano Zampini 
9014a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
9015e456f2a8SStefano Zampini {
9016e456f2a8SStefano Zampini   IS             localis_t;
9017a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
9018e456f2a8SStefano Zampini   PetscScalar    *vals;
9019e456f2a8SStefano Zampini   PetscErrorCode ierr;
9020e456f2a8SStefano Zampini 
9021e456f2a8SStefano Zampini   PetscFunctionBegin;
9022a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
9023e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
9024854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
9025e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
9026e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
9027a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
9028a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
90291035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
90303151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
9031a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
90321035eff8SStefano Zampini   }
9033a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
9034e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
9035e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
9036a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
9037a7dc3881SStefano Zampini   /* now compute set in local ordering */
9038a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9039a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9040a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
9041a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
9042a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9043ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9044e456f2a8SStefano Zampini       lsize++;
9045e456f2a8SStefano Zampini     }
9046e456f2a8SStefano Zampini   }
9047854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
9048a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9049ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9050e456f2a8SStefano Zampini       idxs[lsize++] = i;
9051e456f2a8SStefano Zampini     }
9052e456f2a8SStefano Zampini   }
9053a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
9054a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
9055e456f2a8SStefano Zampini   *localis = localis_t;
9056e456f2a8SStefano Zampini   PetscFunctionReturn(0);
9057e456f2a8SStefano Zampini }
9058906d46d4SStefano Zampini 
905908122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
9060b96c3477SStefano Zampini {
9061a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9062b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9063b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
9064a64f4aa4SStefano Zampini   Mat                 S_j;
9065b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
9066b96c3477SStefano Zampini   PetscBool           free_used_adj;
9067b96c3477SStefano Zampini   PetscErrorCode      ierr;
9068b96c3477SStefano Zampini 
9069b96c3477SStefano Zampini   PetscFunctionBegin;
907043371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
9071b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
9072b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
907308122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
9074b96c3477SStefano Zampini     used_xadj = NULL;
9075b96c3477SStefano Zampini     used_adjncy = NULL;
9076b96c3477SStefano Zampini   } else {
907708122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
907808122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
907908122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
908008122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
9081b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
9082b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
9083b96c3477SStefano Zampini     } else {
90842fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
9085b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
9086b96c3477SStefano Zampini       PetscInt       nvtxs;
9087b96c3477SStefano Zampini 
90882fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
90892fffb893SStefano Zampini       if (flg_row) {
9090b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
9091580bdb30SBarry Smith         ierr = PetscArraycpy(used_xadj,xadj,nvtxs+1);CHKERRQ(ierr);
9092580bdb30SBarry Smith         ierr = PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
9093b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
90942fffb893SStefano Zampini       } else {
90952fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
90962fffb893SStefano Zampini         used_xadj = NULL;
90972fffb893SStefano Zampini         used_adjncy = NULL;
90982fffb893SStefano Zampini       }
90992fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
9100b96c3477SStefano Zampini     }
9101b96c3477SStefano Zampini   }
9102d5574798SStefano Zampini 
9103d5574798SStefano Zampini   /* setup sub_schurs data */
91042f37b69bSStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
9105df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
9106df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
9107a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
910891af6908SStefano 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);
9109a64f4aa4SStefano Zampini   } else {
911072b8c272SStefano Zampini     Mat       change = NULL;
91119d54b7f4SStefano Zampini     Vec       scaling = NULL;
9112111315fdSstefano_zampini     IS        change_primal = NULL, iP;
9113111315fdSstefano_zampini     PetscInt  benign_n;
9114111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
91157ebab0bbSStefano Zampini     PetscBool need_change = PETSC_FALSE;
9116111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
9117a3df083aSStefano Zampini 
91185feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
91195feab87aSStefano Zampini       PetscInt n_vertices;
91205feab87aSStefano Zampini 
91215feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
91222034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
91235feab87aSStefano Zampini     }
9124a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
9125a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
9126ca92afb2SStefano Zampini     } else {
9127a3df083aSStefano Zampini       benign_n = 0;
9128ca92afb2SStefano Zampini     }
9129b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
9130b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
9131b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
913272b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
913322db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
9134820f2d46SBarry Smith       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
913522db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
9136b7ab4a40SStefano Zampini     }
9137b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
9138b7ab4a40SStefano 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 */
9139b7ab4a40SStefano Zampini     if (need_change) {
914088c03ad3SStefano Zampini       PC_IS   *pcisf;
914188c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
914288c03ad3SStefano Zampini       PC      pcf;
914388c03ad3SStefano Zampini 
9144e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
914588c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
914688c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
914788c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
9148b9be95fcSstefano_zampini 
914988c03ad3SStefano Zampini       /* hacks */
915088c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
915172b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
915272b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
915372b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
915472b8c272SStefano Zampini       pcisf->n                     = pcis->n;
915572b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
915688c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
915788c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
915888c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
915988c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
916088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
916188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
916272b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
916388c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
9164b9be95fcSstefano_zampini 
9165b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
916688c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
916772b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
916872b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
916972b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
917072b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
9171b9be95fcSstefano_zampini 
917288c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
917372b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
917488c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
917588c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
917688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
917788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
917888c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
917988c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
9180b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
918188c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
918288c03ad3SStefano Zampini     }
91839d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
9184111315fdSstefano_zampini 
9185111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
9186111315fdSstefano_zampini     if (iP) {
9187111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
9188111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
9189111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
9190111315fdSstefano_zampini     }
9191111315fdSstefano_zampini     if (discrete_harmonic) {
9192111315fdSstefano_zampini       Mat A;
9193111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
9194111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
9195111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
9196111315fdSstefano_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);
9197111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
9198111315fdSstefano_zampini     } else {
919991af6908SStefano 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);
9200111315fdSstefano_zampini     }
920172b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
920272b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
9203ca92afb2SStefano Zampini   }
9204d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9205b96c3477SStefano Zampini 
9206b96c3477SStefano Zampini   /* free adjacency */
9207b96c3477SStefano Zampini   if (free_used_adj) {
9208b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
9209b96c3477SStefano Zampini   }
921043371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
9211b96c3477SStefano Zampini   PetscFunctionReturn(0);
9212b96c3477SStefano Zampini }
9213b96c3477SStefano Zampini 
921408122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
9215b96c3477SStefano Zampini {
9216b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9217b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9218b96c3477SStefano Zampini   PCBDDCGraph         graph;
9219b96c3477SStefano Zampini   PetscErrorCode      ierr;
9220b96c3477SStefano Zampini 
9221b96c3477SStefano Zampini   PetscFunctionBegin;
9222b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
922308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
92243301b35fSStefano Zampini     IS       verticesIS,verticescomm;
92253301b35fSStefano Zampini     PetscInt vsize,*idxs;
9226b96c3477SStefano Zampini 
9227b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
92283301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
92293301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
92303301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
92313301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
9232c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
9233b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
9234be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
9235441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
92363301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
9237b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
9238b96c3477SStefano Zampini   } else {
9239b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
9240b96c3477SStefano Zampini   }
9241e4d548c7SStefano Zampini   /* print some info */
92425c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
9243e4d548c7SStefano Zampini     IS       vertices;
9244e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
9245c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
9246e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9247e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
9248e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9249e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
92506080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,(int)nv,pcbddc->use_vertices);CHKERRQ(ierr);
92516080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%D)\n",PetscGlobalRank,(int)nedges,pcbddc->use_edges);CHKERRQ(ierr);
92526080607fSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%D)\n",PetscGlobalRank,(int)nfaces,pcbddc->use_faces);CHKERRQ(ierr);
9253e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
9254e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
9255c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
9256e4d548c7SStefano Zampini   }
9257b96c3477SStefano Zampini 
9258b96c3477SStefano Zampini   /* sub_schurs init */
9259b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
9260b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
9261b334f244SStefano Zampini   }
926288113c35SStefano 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);
9263a64f4aa4SStefano Zampini 
9264b96c3477SStefano Zampini   /* free graph struct */
926508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
9266b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
9267b96c3477SStefano Zampini   }
9268b96c3477SStefano Zampini   PetscFunctionReturn(0);
9269b96c3477SStefano Zampini }
9270fa34dd3eSStefano Zampini 
9271fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
9272fa34dd3eSStefano Zampini {
9273fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9274fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9275fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
9276fa34dd3eSStefano Zampini 
9277fa34dd3eSStefano Zampini   PetscFunctionBegin;
9278fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
9279fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
92804f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
9281fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
92824f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
928375c01103SStefano Zampini     PetscReal      norm;
9284fa34dd3eSStefano Zampini     PetscInt       i;
9285fa34dd3eSStefano Zampini 
9286fa34dd3eSStefano Zampini     /* B0 and B0_B */
9287fa34dd3eSStefano Zampini     if (zerodiag) {
9288fa34dd3eSStefano Zampini       IS       dummy;
9289fa34dd3eSStefano Zampini 
92904f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
92917dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
9292fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
9293fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
9294fa34dd3eSStefano Zampini     }
9295fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
9296fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
9297fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
9298fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9299fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9300fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9301fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9302fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
9303fa34dd3eSStefano Zampini     /* S_j */
93042f37b69bSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
9305fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
9306fa34dd3eSStefano Zampini 
9307fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
9308fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
9309fa34dd3eSStefano Zampini     /* continuous in primal space */
9310fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
9311fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9312fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9313fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
93144f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
93154f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
9316fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9317fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9318fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9319fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9320fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9321fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9322fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
9323fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
9324fa34dd3eSStefano Zampini 
9325fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
9326fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
9327fa34dd3eSStefano Zampini     /* local with Schur */
9328fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
9329fa34dd3eSStefano Zampini     if (zerodiag) {
9330fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
93314f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
9332fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9333fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
9334fa34dd3eSStefano Zampini     }
9335fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
9336fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9337fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9338fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9339fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9340fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
9341fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
9342fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9343fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
9344fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9345fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9346fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9347fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9348fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9349fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
9350fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
9351fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
9352fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
9353fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
9354fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
9355fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9356fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9357fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9358fa34dd3eSStefano Zampini     if (zerodiag) {
9359fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
9360fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
93614f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
9362fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
9363fa34dd3eSStefano Zampini     }
9364fa34dd3eSStefano Zampini     /* BDDC */
9365fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
9366fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
9367fa34dd3eSStefano Zampini 
9368fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
9369fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
9370fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
93716080607fSStefano Zampini     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);CHKERRQ(ierr);
93724f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
93736080607fSStefano Zampini       ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%D] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));CHKERRQ(ierr);
9374fa34dd3eSStefano Zampini     }
93754f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
9376fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
9377fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
9378fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
9379fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
9380fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
9381fa34dd3eSStefano Zampini   }
9382fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9383fa34dd3eSStefano Zampini }
93841e0482f5SStefano Zampini 
93851e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
93861e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
93871e0482f5SStefano Zampini {
93881e0482f5SStefano Zampini   Mat            At;
93891e0482f5SStefano Zampini   IS             rows;
93901e0482f5SStefano Zampini   PetscInt       rst,ren;
93911e0482f5SStefano Zampini   PetscErrorCode ierr;
93921e0482f5SStefano Zampini   PetscLayout    rmap;
93931e0482f5SStefano Zampini 
93941e0482f5SStefano Zampini   PetscFunctionBegin;
93951e0482f5SStefano Zampini   rst = ren = 0;
93961e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93971e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
93981e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
93991e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
94001e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
94011e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
94021e0482f5SStefano Zampini   }
9403e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
94047dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
94051e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
94061e0482f5SStefano Zampini 
94071e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
94081e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
94091e0482f5SStefano Zampini     IS         from,to;
94101e0482f5SStefano Zampini     Vec        gvec;
94111e0482f5SStefano Zampini     PetscInt   lsize;
94121e0482f5SStefano Zampini 
94131e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
94141e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
94151e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
94161e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
94171e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
94181e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
94191e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
9420ffc4695bSBarry Smith     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRMPI(ierr);
9421ffc4695bSBarry Smith     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRMPI(ierr);
94221e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
94231e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
94241e0482f5SStefano Zampini     b->A = a->A;
94251e0482f5SStefano Zampini     b->B = a->B;
94261e0482f5SStefano Zampini 
94271e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
94281e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
94290a545947SLisandro Dalcin     b->rowindices      = NULL;
94300a545947SLisandro Dalcin     b->rowvalues       = NULL;
94311e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
94321e0482f5SStefano Zampini 
94331e0482f5SStefano Zampini     (*B)->rmap         = rmap;
94341e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
94351e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
94361e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
94371e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
94381e0482f5SStefano Zampini 
94391e0482f5SStefano Zampini     if (a->colmap) {
94401e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
94411e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
94421e0482f5SStefano Zampini #else
94431e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
94441e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
9445580bdb30SBarry Smith       ierr = PetscArraycpy(b->colmap,a->colmap,At->cmap->N);CHKERRQ(ierr);
94461e0482f5SStefano Zampini #endif
94470a545947SLisandro Dalcin     } else b->colmap = NULL;
94481e0482f5SStefano Zampini     if (a->garray) {
94491e0482f5SStefano Zampini       PetscInt len;
94501e0482f5SStefano Zampini       len  = a->B->cmap->n;
94511e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
94521e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
9453580bdb30SBarry Smith       if (len) { ierr = PetscArraycpy(b->garray,a->garray,len);CHKERRQ(ierr); }
94540a545947SLisandro Dalcin     } else b->garray = NULL;
94551e0482f5SStefano Zampini 
94561e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
94571e0482f5SStefano Zampini     b->lvec = a->lvec;
94581e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
94591e0482f5SStefano Zampini 
94601e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
94611e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
94621e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
94631e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
94641e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
94659448b7f1SJunchao Zhang     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
94661e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
94671e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
94681e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
94691e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
94701e0482f5SStefano Zampini   }
94711e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
94721e0482f5SStefano Zampini   PetscFunctionReturn(0);
94731e0482f5SStefano Zampini }
9474