xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 837cedc9649dc833b7c8312303fdb31ff425e118)
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>
4*837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h>
5c80a6c00SStefano Zampini #include <petscdmplex.h>
6674ae819SStefano Zampini #include <petscblaslapack.h>
7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h>
97620a527SStefano Zampini #include <petscdmda.h>
10674ae819SStefano Zampini 
111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
121e0482f5SStefano Zampini 
13f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
14f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
16a13144ffSStefano Zampini {
17a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
18a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
19a13144ffSStefano Zampini   PetscReal      *sing;
20a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
21a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
22a13144ffSStefano Zampini   PetscErrorCode ierr;
23a13144ffSStefano Zampini 
24a13144ffSStefano Zampini   PetscFunctionBegin;
25a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
26a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
27614dbb09SStefano Zampini #else
28a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
29a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
30a13144ffSStefano Zampini 
31a13144ffSStefano Zampini   /* workspace */
32a13144ffSStefano Zampini   if (!work) {
33a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
34f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
35a13144ffSStefano Zampini   } else {
36a13144ffSStefano Zampini     ulw   = lw;
37a13144ffSStefano Zampini     uwork = work;
38a13144ffSStefano Zampini   }
39a13144ffSStefano Zampini   n = PetscMin(nr,nc);
40a13144ffSStefano Zampini   if (!rwork) {
41a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
42a13144ffSStefano Zampini   } else {
43a13144ffSStefano Zampini     sing = rwork;
44a13144ffSStefano Zampini   }
45a13144ffSStefano Zampini 
46a13144ffSStefano Zampini   /* SVD */
47a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
51a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
54a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
55a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
56a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
57a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
58a13144ffSStefano Zampini   if (!rwork) {
59a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   if (!work) {
62a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
63a13144ffSStefano Zampini   }
64a13144ffSStefano Zampini   /* create B */
65f498cd09SStefano Zampini   if (!range) {
66a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
67a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
68a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
69f498cd09SStefano Zampini   } else {
70f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
71f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
72f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
73f498cd09SStefano Zampini   }
74a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
75a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
76614dbb09SStefano Zampini #endif
77614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
78a13144ffSStefano Zampini   PetscFunctionBegin;
79a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
80a13144ffSStefano Zampini #endif
81a13144ffSStefano Zampini   PetscFunctionReturn(0);
82a13144ffSStefano Zampini }
83a13144ffSStefano Zampini 
841e0482f5SStefano Zampini /* TODO REMOVE */
851e0482f5SStefano Zampini #if defined(PRINT_GDET)
861e0482f5SStefano Zampini static int inc = 0;
871e0482f5SStefano Zampini static int lev = 0;
881e0482f5SStefano Zampini #endif
891e0482f5SStefano Zampini 
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
1057dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
1137dae84e0SHong Zhang   ierr = MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1237dae84e0SHong Zhang     ierr = MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
156a13144ffSStefano Zampini {
157a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
158a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1590569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
160eee23b56SStefano Zampini   Vec                    tvec;
161a13144ffSStefano Zampini   PetscSF                sfv;
1621e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
163a13144ffSStefano Zampini   MPI_Comm               comm;
164c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
165c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1667d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
167a13144ffSStefano Zampini   PetscScalar            *vals,*work;
168a13144ffSStefano Zampini   PetscReal              *rwork;
169a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1701e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
171a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
172eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
173b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
174a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
175b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
176637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
177b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
178b03ebc13SStefano Zampini   PetscInt               *emarks;
179b03ebc13SStefano Zampini #endif
180213b8bfaSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global,singular,setprimal;
181a13144ffSStefano Zampini   PetscErrorCode         ierr;
182a13144ffSStefano Zampini 
183a13144ffSStefano Zampini   PetscFunctionBegin;
184213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
185213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
186213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
187213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
188213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
189213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
190213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
191213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
192a13144ffSStefano Zampini   print      = PETSC_FALSE;
193213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
194a13144ffSStefano Zampini 
195213b8bfaSStefano Zampini   /* Command line customization */
196213b8bfaSStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr);
197213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL);CHKERRQ(ierr);
198213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL);CHKERRQ(ierr);
199213b8bfaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL);CHKERRQ(ierr);
200213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
201213b8bfaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL);CHKERRQ(ierr);
202213b8bfaSStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
203213b8bfaSStefano Zampini 
204213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2051e0482f5SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
2061e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
207213b8bfaSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
208213b8bfaSStefano Zampini   if (!singular) {
209a13144ffSStefano Zampini     ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
210a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
211c2151214SStefano Zampini     for (i=0;i<n;i++) {
212a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
213a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
214a13144ffSStefano Zampini         break;
215a13144ffSStefano Zampini       }
216a13144ffSStefano Zampini     }
217a13144ffSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218a13144ffSStefano Zampini     ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
219a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
220213b8bfaSStefano Zampini   }
221a13144ffSStefano Zampini 
222213b8bfaSStefano Zampini   /* Get Nedelec field */
223213b8bfaSStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
224c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= pcbddc->n_ISForDofsLocal) SETERRQ2(comm,PETSC_ERR_USER,"Invalid field for Nedelec %d: number of fields is %d",field,pcbddc->n_ISForDofsLocal);
225213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
226c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
227c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
228c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
229213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
230213b8bfaSStefano Zampini     ne            = n;
231213b8bfaSStefano Zampini     nedfieldlocal = NULL;
232213b8bfaSStefano Zampini     global        = PETSC_TRUE;
233213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
234213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
235213b8bfaSStefano Zampini 
236213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
237213b8bfaSStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
238213b8bfaSStefano Zampini     ierr = MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren);CHKERRQ(ierr);
239213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
240213b8bfaSStefano Zampini       PetscInt nc;
241213b8bfaSStefano Zampini 
242213b8bfaSStefano Zampini       ierr = MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
243213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
244213b8bfaSStefano Zampini       ierr = MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL);CHKERRQ(ierr);
245213b8bfaSStefano Zampini     }
246213b8bfaSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247213b8bfaSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
248213b8bfaSStefano Zampini     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
249213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
250213b8bfaSStefano Zampini     ierr = ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal);CHKERRQ(ierr);
251213b8bfaSStefano Zampini   } else {
252213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
253213b8bfaSStefano Zampini   }
254213b8bfaSStefano Zampini 
255213b8bfaSStefano Zampini   /* Sanity checks */
256213b8bfaSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
257213b8bfaSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
258213b8bfaSStefano Zampini   if (order && ne%order) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %d it's not a multiple of the order %d",ne,order);
259213b8bfaSStefano Zampini 
260213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2611e0482f5SStefano Zampini   if (setprimal) {
262eee23b56SStefano Zampini     IS       enedfieldlocal;
263eee23b56SStefano Zampini     PetscInt *eidxs;
264eee23b56SStefano Zampini 
265eee23b56SStefano Zampini     ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
266eee23b56SStefano Zampini     ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
267213b8bfaSStefano Zampini     if (nedfieldlocal) {
268213b8bfaSStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
269eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
270eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
271eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
272eee23b56SStefano Zampini         }
273eee23b56SStefano Zampini       }
274eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
275213b8bfaSStefano Zampini     } else {
276213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
277213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
278213b8bfaSStefano Zampini           eidxs[cum++] = i;
279213b8bfaSStefano Zampini         }
280213b8bfaSStefano Zampini       }
281213b8bfaSStefano Zampini     }
282213b8bfaSStefano Zampini     ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
283eee23b56SStefano Zampini     ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
284eee23b56SStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
285eee23b56SStefano Zampini     ierr = PetscFree(eidxs);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
287eee23b56SStefano Zampini     ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2881e0482f5SStefano Zampini     PetscFunctionReturn(0);
2891e0482f5SStefano Zampini   }
290a13144ffSStefano Zampini 
291213b8bfaSStefano Zampini   /* Compute some l2g maps */
292213b8bfaSStefano Zampini   if (nedfieldlocal) {
293c2151214SStefano Zampini     IS is;
294c2151214SStefano Zampini 
295c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
296c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2981e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2991e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
3001e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
3011e0482f5SStefano Zampini     if (global) {
3021e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3031e0482f5SStefano Zampini       el2g = al2g;
3041e0482f5SStefano Zampini     } else {
3051e0482f5SStefano Zampini       IS gis;
3061e0482f5SStefano Zampini 
3071e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
3081e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
3091e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
3101e0482f5SStefano Zampini     }
311c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
312c2151214SStefano Zampini   } else {
3131e0482f5SStefano Zampini     /* restore default */
3141e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3151e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3161e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3171e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
3181e0482f5SStefano Zampini     el2g = al2g;
319c2151214SStefano Zampini     fl2g = NULL;
320c2151214SStefano Zampini   }
321a13144ffSStefano Zampini 
322213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
323c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
324c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
325c2151214SStefano Zampini   if (nedfieldlocal) {
326c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
327c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
328c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
329c2151214SStefano Zampini   } else {
330c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
331c2151214SStefano Zampini   }
332c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
333c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
334213b8bfaSStefano Zampini 
335213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
336213b8bfaSStefano Zampini     ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
337213b8bfaSStefano Zampini     ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     if (global) {
3391e0482f5SStefano Zampini       PetscInt rst;
3401e0482f5SStefano Zampini 
341c2151214SStefano Zampini       ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
342c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
343c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
344c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
345c2151214SStefano Zampini         }
346c2151214SStefano Zampini       }
347a13144ffSStefano Zampini       ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
348c2151214SStefano Zampini       ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3491e0482f5SStefano Zampini     } else {
3501e0482f5SStefano Zampini       PetscInt *tbz;
3511e0482f5SStefano Zampini 
3521e0482f5SStefano Zampini       ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3531e0482f5SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3541e0482f5SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3551e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3561e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3571e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3581e0482f5SStefano Zampini           tbz[cum++] = i;
3591e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3601e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3611e0482f5SStefano Zampini       ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3621e0482f5SStefano Zampini       ierr = PetscFree(tbz);CHKERRQ(ierr);
3631e0482f5SStefano Zampini     }
364213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
365213b8bfaSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->discretegradient);CHKERRQ(ierr);
366213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
367213b8bfaSStefano Zampini   }
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
370a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
3727dae84e0SHong Zhang   ierr = MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
373a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
378a13144ffSStefano Zampini 
379213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
380c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
381a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
387a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
388213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
389213b8bfaSStefano Zampini   ierr = PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots);CHKERRQ(ierr);
390a13144ffSStefano Zampini 
3911e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
392213b8bfaSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
393a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
394213b8bfaSStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
395a13144ffSStefano Zampini 
396213b8bfaSStefano Zampini   if (print) {
397213b8bfaSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
398213b8bfaSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
399213b8bfaSStefano Zampini   }
400213b8bfaSStefano Zampini 
401213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
4020569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
4030569b399SStefano Zampini 
404a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4054e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
4064e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
4107d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
411c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
412a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
413a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
414a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
415c2151214SStefano Zampini     IS is;
416c2151214SStefano Zampini 
417c2151214SStefano Zampini     if (fl2g) {
418c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
419c2151214SStefano Zampini     } else {
420c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
421c2151214SStefano Zampini     }
422c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
423c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
424a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
425a13144ffSStefano Zampini       if (idxs[i] >= 0) {
426a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4277d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
428a13144ffSStefano Zampini       }
429a13144ffSStefano Zampini     }
430c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
431c2151214SStefano Zampini     if (fl2g) {
432c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
433c2151214SStefano Zampini     }
434a13144ffSStefano Zampini   }
435a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
436c2151214SStefano Zampini     IS is;
437c2151214SStefano Zampini 
438c2151214SStefano Zampini     if (fl2g) {
439c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
440c2151214SStefano Zampini     } else {
441c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
442c2151214SStefano Zampini     }
443c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
444c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
445a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
446a13144ffSStefano Zampini       if (idxs[i] >= 0) {
447a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
448a13144ffSStefano Zampini       }
449a13144ffSStefano Zampini     }
450c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
451c2151214SStefano Zampini     if (fl2g) {
452c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
453a13144ffSStefano Zampini     }
454c2151214SStefano Zampini   }
455c2151214SStefano Zampini 
456213b8bfaSStefano Zampini   /* Count neighs per dof */
457637e8532SStefano Zampini   ierr = PetscCalloc1(ne,&ecount);CHKERRQ(ierr);
458637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&eneighs);CHKERRQ(ierr);
459637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
460637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
461637e8532SStefano Zampini     cum += n_shared[i];
462637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
463637e8532SStefano Zampini       ecount[shared[i][j]]++;
464637e8532SStefano Zampini     }
465637e8532SStefano Zampini   }
466637e8532SStefano Zampini   if (ne) {
467637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&eneighs[0]);CHKERRQ(ierr);
468637e8532SStefano Zampini   }
469637e8532SStefano Zampini   for (i=1;i<ne;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
470637e8532SStefano Zampini   ierr = PetscMemzero(ecount,ne*sizeof(PetscInt));CHKERRQ(ierr);
471637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
472637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
473637e8532SStefano Zampini       PetscInt k = shared[i][j];
474637e8532SStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
475637e8532SStefano Zampini       ecount[k]++;
476637e8532SStefano Zampini     }
477637e8532SStefano Zampini   }
478637e8532SStefano Zampini   for (i=0;i<ne;i++) {
479637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr);
480637e8532SStefano Zampini   }
481637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
482637e8532SStefano Zampini   ierr = PetscCalloc1(nv,&vcount);CHKERRQ(ierr);
483637e8532SStefano Zampini   ierr = PetscMalloc1(nv,&vneighs);CHKERRQ(ierr);
484637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
485637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
486637e8532SStefano Zampini     cum += n_shared[i];
487637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
488637e8532SStefano Zampini       vcount[shared[i][j]]++;
489637e8532SStefano Zampini     }
490637e8532SStefano Zampini   }
491637e8532SStefano Zampini   if (nv) {
492637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&vneighs[0]);CHKERRQ(ierr);
493637e8532SStefano Zampini   }
494637e8532SStefano Zampini   for (i=1;i<nv;i++) vneighs[i] = vneighs[i-1] + vcount[i-1];
495637e8532SStefano Zampini   ierr = PetscMemzero(vcount,nv*sizeof(PetscInt));CHKERRQ(ierr);
496637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
497637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
498637e8532SStefano Zampini       PetscInt k = shared[i][j];
499637e8532SStefano Zampini       vneighs[k][vcount[k]] = neigh[i];
500637e8532SStefano Zampini       vcount[k]++;
501637e8532SStefano Zampini     }
502637e8532SStefano Zampini   }
503637e8532SStefano Zampini   for (i=0;i<nv;i++) {
504637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&vcount[i],vneighs[i]);CHKERRQ(ierr);
505637e8532SStefano Zampini   }
506637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
507637e8532SStefano Zampini 
5087d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
5097d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
51062b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
51162b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
5127d871cd7SStefano Zampini     if ((ecount[i] > 1 && !PetscBTLookup(btbd,i)) || (ecount[i] == 1 && PetscBTLookup(btb,i))) {
51362b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
51462b0c6f7SStefano Zampini     }
51562b0c6f7SStefano Zampini   }
516637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
51762b0c6f7SStefano Zampini   if (!conforming) {
51862b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
51962b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
52062b0c6f7SStefano Zampini   }
5214e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
522dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
52362b0c6f7SStefano Zampini   cum  = 0;
524a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
525dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
52662b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
527a13144ffSStefano Zampini       marks[cum++] = i;
528dec27d64SStefano Zampini       continue;
529dec27d64SStefano Zampini     }
530dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
53162b0c6f7SStefano Zampini     if (!conforming) {
53262b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
533a13144ffSStefano Zampini         marks[cum++] = i;
534a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
535a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
536a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
537a13144ffSStefano Zampini         }
53862b0c6f7SStefano Zampini       } else {
53962b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
54062b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
54162b0c6f7SStefano Zampini            - at most 2 endpoints
54262b0c6f7SStefano Zampini            - order-1 interior nodal dofs
54362b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
54462b0c6f7SStefano Zampini         */
54562b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
54662b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
54762b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
54862b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
54962b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
55062b0c6f7SStefano Zampini           if (nconn > order) ends++;
55162b0c6f7SStefano Zampini           else if (nconn == order) ints++;
55262b0c6f7SStefano Zampini           else undef++;
55362b0c6f7SStefano Zampini         }
55462b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
55562b0c6f7SStefano Zampini           marks[cum++] = i;
55662b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
55762b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
55862b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
55962b0c6f7SStefano Zampini           }
56062b0c6f7SStefano Zampini         }
56162b0c6f7SStefano Zampini       }
562a13144ffSStefano Zampini     }
563dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
564dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
565dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
566dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
567a13144ffSStefano Zampini     }
568dec27d64SStefano Zampini   }
56962b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
570dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5714e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
57262b0c6f7SStefano Zampini   if (!conforming) {
57362b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
57462b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
57562b0c6f7SStefano Zampini   }
5764e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
577637e8532SStefano Zampini 
578b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5794e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
580a13144ffSStefano Zampini   if (print) {
5814e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5824e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5834e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
584a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
585a13144ffSStefano Zampini   }
586a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
587dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
588a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
589637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5907d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
591b03ebc13SStefano Zampini     if (!order) { /* variable order */
592dec27d64SStefano Zampini       PetscReal vorder = 0.;
593dec27d64SStefano Zampini 
594dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
595dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
596dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
597dec27d64SStefano Zampini       ord  = 1;
598dec27d64SStefano Zampini     }
599a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
600dec27d64SStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",test,i,ord);
601a13144ffSStefano Zampini #endif
602637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
6037d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
6047d871cd7SStefano Zampini         bdir = PETSC_TRUE;
6057d871cd7SStefano Zampini         break;
6067d871cd7SStefano Zampini       }
607637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
608637e8532SStefano Zampini         sneighs = PETSC_FALSE;
609637e8532SStefano Zampini       } else {
610637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
611637e8532SStefano Zampini         for (k=0;k<vc;k++) {
612637e8532SStefano Zampini           if (vn[k] != en[k]) {
613637e8532SStefano Zampini             sneighs = PETSC_FALSE;
614637e8532SStefano Zampini             break;
615637e8532SStefano Zampini           }
616637e8532SStefano Zampini         }
617637e8532SStefano Zampini       }
618637e8532SStefano Zampini     }
6197d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
6207d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
621a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
622dec27d64SStefano Zampini     } else if (test == ord) {
623b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
624a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
625a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
626a13144ffSStefano Zampini       } else {
627a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
628a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
629a13144ffSStefano Zampini       }
630a13144ffSStefano Zampini     }
631a13144ffSStefano Zampini   }
632637e8532SStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
633637e8532SStefano Zampini   ierr = PetscFree(vcount);CHKERRQ(ierr);
634637e8532SStefano Zampini   if (ne) {
635637e8532SStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
636637e8532SStefano Zampini   }
637637e8532SStefano Zampini   if (nv) {
638637e8532SStefano Zampini     ierr = PetscFree(vneighs[0]);CHKERRQ(ierr);
639637e8532SStefano Zampini   }
640637e8532SStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
641637e8532SStefano Zampini   ierr = PetscFree(vneighs);CHKERRQ(ierr);
6427d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
643b03ebc13SStefano Zampini 
644b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
645b03ebc13SStefano Zampini   if (order != 1) {
646b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
647b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
648b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
649b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
650b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
651b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
652b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
653b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
654b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
655b03ebc13SStefano Zampini             PetscInt v = jjt[k];
656b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
657b03ebc13SStefano Zampini               found = PETSC_TRUE;
658b03ebc13SStefano Zampini               break;
659b03ebc13SStefano Zampini             }
660b03ebc13SStefano Zampini           }
661b03ebc13SStefano Zampini         }
662b03ebc13SStefano Zampini         if (!found) {
663b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
664b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
665b03ebc13SStefano Zampini         } else {
666b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
667b03ebc13SStefano Zampini         }
668b03ebc13SStefano Zampini       }
669b03ebc13SStefano Zampini     }
670b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
671b03ebc13SStefano Zampini   }
672dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
673a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
674b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
675a13144ffSStefano Zampini 
676a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6770569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
678a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6794e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
680a13144ffSStefano Zampini 
6814e64d54eSstefano_zampini   /* Mark interior nodal dofs */
682a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6834e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
684a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
685a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6864e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
687a13144ffSStefano Zampini     }
688a13144ffSStefano Zampini   }
689a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
690a13144ffSStefano Zampini 
691a13144ffSStefano Zampini   /* communicate corners and splitpoints */
692a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
693a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
694a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
695a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
696a13144ffSStefano Zampini 
697a13144ffSStefano Zampini   if (print) {
698a13144ffSStefano Zampini     IS tbz;
699a13144ffSStefano Zampini 
700a13144ffSStefano Zampini     cum = 0;
701a13144ffSStefano Zampini     for (i=0;i<nv;i++)
702a13144ffSStefano Zampini       if (sfvleaves[i])
703a13144ffSStefano Zampini         vmarks[cum++] = i;
704a13144ffSStefano Zampini 
705a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
706a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
707a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
708a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
709a13144ffSStefano Zampini   }
710a13144ffSStefano Zampini 
711a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
712a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
713a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
715a13144ffSStefano Zampini 
7164e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
7174e64d54eSstefano_zampini      and interior nodal dofs */
718a13144ffSStefano Zampini   cum = 0;
719a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
720a13144ffSStefano Zampini     if (sfvleaves[i]) {
721a13144ffSStefano Zampini       vmarks[cum++] = i;
722a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
723a13144ffSStefano Zampini     }
7244e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
725a13144ffSStefano Zampini   }
7264e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
727a13144ffSStefano Zampini   if (print) {
728a13144ffSStefano Zampini     IS tbz;
729a13144ffSStefano Zampini 
730a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
7314e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
732a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
733a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
734a13144ffSStefano Zampini   }
735a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
736a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
737a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
738a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
739a13144ffSStefano Zampini 
740a13144ffSStefano Zampini   /* Recompute G */
741a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
742a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
743a13144ffSStefano Zampini   if (print) {
744a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
745a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
746a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
747a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
748a13144ffSStefano Zampini   }
749a13144ffSStefano Zampini 
750a13144ffSStefano Zampini   /* Get primal dofs (if any) */
751a13144ffSStefano Zampini   cum = 0;
752a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
753a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
754a13144ffSStefano Zampini   }
755c2151214SStefano Zampini   if (fl2g) {
756c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
757c2151214SStefano Zampini   }
758a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
759a13144ffSStefano Zampini   if (print) {
760a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
761a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
762a13144ffSStefano Zampini   }
763a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
764c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
765a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
766a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
767a13144ffSStefano Zampini 
768a13144ffSStefano Zampini   /* Compute edge connectivity */
769a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
770a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
771a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
772c2151214SStefano Zampini   if (fl2g) {
773c2151214SStefano Zampini     PetscBT   btf;
774c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
775c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
776c2151214SStefano Zampini 
777c2151214SStefano Zampini     /* create CSR for all local dofs */
778c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
779c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
780c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %d. Should be %d\n",pcbddc->mat_graph->nvtxs_csr,n);
781c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
782c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
783c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
784c2151214SStefano Zampini       rest = PETSC_TRUE;
785c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
786c2151214SStefano Zampini     } else {
787c2151214SStefano Zampini       free   = PETSC_TRUE;
788c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
789c2151214SStefano Zampini       iiu[0] = 0;
790c2151214SStefano Zampini       for (i=0;i<n;i++) {
791c2151214SStefano Zampini         iiu[i+1] = i+1;
792c2151214SStefano Zampini         jju[i]   = -1;
793d904f53bSStefano Zampini       }
794c2151214SStefano Zampini     }
795c2151214SStefano Zampini 
796c2151214SStefano Zampini     /* import sizes of CSR */
797c2151214SStefano Zampini     iia[0] = 0;
798c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
799c2151214SStefano Zampini 
800c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
801c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
802c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
803c2151214SStefano Zampini     for (i=0;i<ne;i++) {
804c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
805c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
806c2151214SStefano Zampini     }
807c2151214SStefano Zampini 
808c2151214SStefano Zampini     /* iia in CSR */
809c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
810c2151214SStefano Zampini 
811c2151214SStefano Zampini     /* jja in CSR */
812c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
813c2151214SStefano Zampini     for (i=0;i<n;i++)
814c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
815c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
816c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
817c2151214SStefano Zampini 
818c2151214SStefano Zampini     /* map edge dofs connectivity */
8191e0482f5SStefano Zampini     if (jj) {
820c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
821c2151214SStefano Zampini       for (i=0;i<ne;i++) {
822c2151214SStefano Zampini         PetscInt e = idxs[i];
823c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
824c2151214SStefano Zampini       }
8251e0482f5SStefano Zampini     }
826c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
827c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
828c2151214SStefano Zampini     if (rest) {
829c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
830c2151214SStefano Zampini     }
831c2151214SStefano Zampini     if (free) {
832c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
833c2151214SStefano Zampini     }
834c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
835c2151214SStefano Zampini   } else {
836c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
837c2151214SStefano Zampini   }
838c2151214SStefano Zampini 
839a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
840a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
841213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
842a13144ffSStefano Zampini 
843a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
844c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
845a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
846a13144ffSStefano Zampini 
847c2151214SStefano Zampini   if (fl2g) {
848c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
849c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
850c2151214SStefano Zampini     for (i=0;i<nee;i++) {
851c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
852c2151214SStefano Zampini     }
853c2151214SStefano Zampini   } else {
854c2151214SStefano Zampini     eedges  = alleedges;
855c2151214SStefano Zampini     primals = allprimals;
856c2151214SStefano Zampini   }
857c2151214SStefano Zampini 
858a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
859a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
860c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
861c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
862c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
863c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
864c2151214SStefano Zampini   if (print) {
865c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
866c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
867c2151214SStefano Zampini   }
868c2151214SStefano Zampini 
869c2151214SStefano Zampini   maxsize = 0;
870a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
871a13144ffSStefano Zampini     PetscInt size,mark = i+1;
872a13144ffSStefano Zampini 
873a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
874a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
875a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
876a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
877a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
878a13144ffSStefano Zampini   }
879a13144ffSStefano Zampini 
880a13144ffSStefano Zampini   /* Find coarse edge endpoints */
881a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
882a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
883a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
884a13144ffSStefano Zampini     PetscInt mark = i+1,size;
885a13144ffSStefano Zampini 
886a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8871e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8881e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
889a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
890a13144ffSStefano Zampini     if (print) {
891a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
892a13144ffSStefano Zampini       ISView(eedges[i],NULL);
893a13144ffSStefano Zampini     }
894a13144ffSStefano Zampini     for (j=0;j<size;j++) {
895a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
896a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
897a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
898a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
899a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
900a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
901a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
902a13144ffSStefano Zampini           PetscInt  k2;
903a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
904a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
905c2151214SStefano 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]));
906c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
907c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
908c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
909a13144ffSStefano Zampini               corner = PETSC_TRUE;
910a13144ffSStefano Zampini               break;
911a13144ffSStefano Zampini             }
912a13144ffSStefano Zampini           }
913a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
914a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
915a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
916a13144ffSStefano Zampini           } else {
917a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
918a13144ffSStefano Zampini           }
919a13144ffSStefano Zampini         }
920a13144ffSStefano Zampini       }
921a13144ffSStefano Zampini     }
922a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
923a13144ffSStefano Zampini   }
924a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
925a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
926c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
927a13144ffSStefano Zampini 
928a13144ffSStefano Zampini   /* Reset marked primal dofs */
929a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
930a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
931a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
932a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
933a13144ffSStefano Zampini 
9340569b399SStefano Zampini   /* Now use the initial lG */
9350569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
9360569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
9370569b399SStefano Zampini   lG   = lGinit;
9380569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
9390569b399SStefano Zampini 
940a13144ffSStefano Zampini   /* Compute extended cols indices */
941b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
942b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
943a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
945a13144ffSStefano Zampini   i   *= maxsize;
946b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
947a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
948a13144ffSStefano Zampini   eerr = PETSC_FALSE;
949a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
950b03ebc13SStefano Zampini     PetscInt size,found = 0;
951a13144ffSStefano Zampini 
952a13144ffSStefano Zampini     cum  = 0;
953a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9541e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9551e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
956a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
957b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
958a13144ffSStefano Zampini     for (j=0;j<size;j++) {
959a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
960b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
961b03ebc13SStefano Zampini         PetscInt vv = jj[k];
962b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
963b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
964b03ebc13SStefano Zampini       }
965a13144ffSStefano Zampini     }
966a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
967a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
968a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
969a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
970a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
971a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
972a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
973b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
974b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
975a13144ffSStefano Zampini       if (print) {
976a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
977a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
978a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
979a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
980a13144ffSStefano Zampini       }
981a13144ffSStefano Zampini       eerr = PETSC_TRUE;
982a13144ffSStefano Zampini     }
983a13144ffSStefano Zampini   }
9844e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
985a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
986a13144ffSStefano Zampini   if (done) {
987a13144ffSStefano Zampini     PetscInt *newprimals;
988a13144ffSStefano Zampini 
989a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
990a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
991a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
992a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
993a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9940569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
995b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
996a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
997b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
998b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
999a13144ffSStefano Zampini         PetscInt size,mark = i+1;
1000a13144ffSStefano Zampini 
1001a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1002a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1003c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
1004a13144ffSStefano Zampini         for (j=0;j<size;j++) {
1005a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
1006b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
1007a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1008a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
1009a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
1010a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
1011b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
1012b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
1013a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
1014a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
1015a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
1016a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
1017a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
1018b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
1019a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
1020a13144ffSStefano Zampini                   /* finally set the new corners */
1021a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
1022b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
1023a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
1024a13144ffSStefano Zampini                   }
1025a13144ffSStefano Zampini                 }
1026a13144ffSStefano Zampini               }
1027b03ebc13SStefano Zampini             } else {
1028b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
1029a13144ffSStefano Zampini             }
1030a13144ffSStefano Zampini           }
1031a13144ffSStefano Zampini         }
1032b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
1033b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
1034b03ebc13SStefano Zampini 
1035b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
1036b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
1037b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1038b03ebc13SStefano Zampini             PetscInt k2;
1039b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
1040b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
1041b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
1042b03ebc13SStefano Zampini           }
1043b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
1044b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
1045b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
1046b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
1047b03ebc13SStefano Zampini             }
1048b03ebc13SStefano Zampini           }
1049b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
1050b03ebc13SStefano Zampini         }
1051a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1052a13144ffSStefano Zampini       }
1053a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1054a13144ffSStefano Zampini     }
1055b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10560569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1057a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1058c2151214SStefano Zampini     if (fl2g) {
1059c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1060c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1061c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1062c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1063c2151214SStefano Zampini       }
1064c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1065c2151214SStefano Zampini     }
1066c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1067a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1068a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1069a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1070a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1071a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1072213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
1073c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1074c2151214SStefano Zampini     if (fl2g) {
1075c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1076c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1077c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1078c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1079c2151214SStefano Zampini       }
1080c2151214SStefano Zampini     } else {
1081c2151214SStefano Zampini       eedges  = alleedges;
1082c2151214SStefano Zampini       primals = allprimals;
1083c2151214SStefano Zampini     }
1084b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1085a13144ffSStefano Zampini 
1086a13144ffSStefano Zampini     /* Mark again */
1087a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1088a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1089a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1090a13144ffSStefano Zampini 
1091a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1092a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1093a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1094a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1095a13144ffSStefano Zampini     }
1096a13144ffSStefano Zampini     if (print) {
1097a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1098a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1099a13144ffSStefano Zampini     }
1100a13144ffSStefano Zampini 
1101a13144ffSStefano Zampini     /* Recompute extended cols */
1102a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1103a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1104a13144ffSStefano Zampini       PetscInt size;
1105a13144ffSStefano Zampini 
1106a13144ffSStefano Zampini       cum  = 0;
1107a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11081e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
11091e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1110a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1111a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1112a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
11131e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1114a13144ffSStefano Zampini       }
1115a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1116a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1117a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1118a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1119a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1120a13144ffSStefano Zampini       if (cum != size -1) {
1121a13144ffSStefano Zampini         if (print) {
1122a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1123a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1124a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1125a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1126a13144ffSStefano Zampini         }
1127a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1128a13144ffSStefano Zampini       }
1129a13144ffSStefano Zampini     }
1130a13144ffSStefano Zampini   }
1131a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1132a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1133b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
11347d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1135a13144ffSStefano Zampini   /* an error should not occur at this point */
1136a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1137a13144ffSStefano Zampini 
11384e64d54eSstefano_zampini   /* Check the number of endpoints */
11390569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1140b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1141b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
11424e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1143b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
11444e64d54eSstefano_zampini 
1145b03ebc13SStefano Zampini     /* init with defaults */
1146b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
11474e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11481e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
11491e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
11504e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1151b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11524e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11534e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11544e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11554e64d54eSstefano_zampini         PetscInt vv = jj[k];
11564e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1157b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1158b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11594e64d54eSstefano_zampini         }
11604e64d54eSstefano_zampini       }
11614e64d54eSstefano_zampini     }
1162b03ebc13SStefano Zampini     if (found != 2) {
1163b03ebc13SStefano Zampini       PetscInt e;
1164b03ebc13SStefano Zampini       if (fl2g) {
1165b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1166b03ebc13SStefano Zampini       } else {
1167b03ebc13SStefano Zampini         e = idxs[0];
1168b03ebc13SStefano Zampini       }
1169b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1170b03ebc13SStefano Zampini     }
1171eee23b56SStefano Zampini 
1172eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1173b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1174b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1175b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1176b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1177b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1178b03ebc13SStefano Zampini     }
1179eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11804e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1181b03ebc13SStefano 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]);
11824e64d54eSstefano_zampini   }
11830569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11844e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11854e64d54eSstefano_zampini 
1186a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1187a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1188a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1189a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1190a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1191a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1192a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1193a13144ffSStefano Zampini 
1194a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1195a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1196a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1197a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1198a13144ffSStefano Zampini       if (emax < emarks[j]) {
1199a13144ffSStefano Zampini         emax = emarks[j];
1200a13144ffSStefano Zampini         eemax = j;
1201a13144ffSStefano Zampini       }
1202a13144ffSStefano Zampini     }
1203a13144ffSStefano Zampini     /* not relevant for edges */
1204a13144ffSStefano Zampini     if (!eemax) continue;
1205a13144ffSStefano Zampini 
1206a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1207a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1208c2151214SStefano Zampini         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %d and %d) connected through the %d nodal dof at edge dof %d\n",marks[jj[j]]-1,eemax,i,jj[j]);
1209a13144ffSStefano Zampini       }
1210a13144ffSStefano Zampini     }
1211a13144ffSStefano Zampini   }
1212a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1213a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1214a13144ffSStefano Zampini #endif
1215a13144ffSStefano Zampini 
1216a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1217a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1218a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   extmem *= maxsize;
1220a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1221a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1222a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1223a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1224a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1225213b8bfaSStefano Zampini 
1226a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1227a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1228a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1229a13144ffSStefano Zampini         mark = marks[jj[j]];
1230a13144ffSStefano Zampini 
1231a13144ffSStefano Zampini     /* not relevant */
1232a13144ffSStefano Zampini     if (!mark) continue;
1233a13144ffSStefano Zampini 
1234a13144ffSStefano Zampini     /* import extended row */
1235a13144ffSStefano Zampini     mark--;
1236a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1237a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1238a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1239a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1240a13144ffSStefano Zampini     extrowcum[mark] += size;
1241a13144ffSStefano Zampini   }
1242a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1243213b8bfaSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1244213b8bfaSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1245213b8bfaSStefano Zampini 
1246213b8bfaSStefano Zampini   /* Compress extrows */
1247a13144ffSStefano Zampini   cum  = 0;
1248a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1249a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1250a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1251a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1252a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1253a13144ffSStefano Zampini   }
1254a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1255a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1256a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1257a13144ffSStefano Zampini 
1258a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1259a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1260a13144ffSStefano Zampini 
1261a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1262a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1263c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1264c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1265a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1266a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1267a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12681e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1269a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1270a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1271213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1272a13144ffSStefano Zampini 
1273a13144ffSStefano Zampini   /* Defaults to identity */
1274c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1275a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1276a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1277a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1278a13144ffSStefano Zampini 
12791e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12801e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12811e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12821e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12831e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12841e0482f5SStefano Zampini     IS                     wis,gwis;
12851e0482f5SStefano Zampini     PetscInt               cnv,cne;
12861e0482f5SStefano Zampini 
12871e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12881e0482f5SStefano Zampini     if (fl2g) {
12891e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12901e0482f5SStefano Zampini     } else {
12911e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12921e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12931e0482f5SStefano Zampini     }
12941e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12951e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12961e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12971e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12981e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12991e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13001e0482f5SStefano Zampini 
13011e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
13021e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
13031e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13041e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
13051e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
13061e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
13071e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
13081e0482f5SStefano Zampini 
13091e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
13101e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
13111e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
13121e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
13131e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
13141e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
13151e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
13161e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
13171e0482f5SStefano Zampini   }
1318213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
13191e0482f5SStefano Zampini 
13201e0482f5SStefano Zampini #if defined(PRINT_GDET)
13211e0482f5SStefano Zampini   inc = 0;
13221e0482f5SStefano Zampini   lev = pcbddc->current_level;
13231e0482f5SStefano Zampini #endif
1324213b8bfaSStefano Zampini 
1325213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1326a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1327a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
13281e0482f5SStefano Zampini     IS          cornersis = NULL;
13291e0482f5SStefano Zampini     PetscScalar cvals[2];
1330a13144ffSStefano Zampini 
13311e0482f5SStefano Zampini     if (pcbddc->nedcG) {
13321e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
13331e0482f5SStefano Zampini     }
13341e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1335a13144ffSStefano Zampini     if (Gins && GKins) {
1336a13144ffSStefano Zampini       PetscScalar    *data;
1337a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1338a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1339a13144ffSStefano Zampini 
1340a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1341a13144ffSStefano Zampini       /* H1 */
1342a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1343a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1344a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1345a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1346a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1347a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1348a13144ffSStefano Zampini       /* complement */
1349a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
13501e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1351213b8bfaSStefano 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);
1352213b8bfaSStefano 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);
1353a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1354a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1355a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13561e0482f5SStefano Zampini 
13571e0482f5SStefano Zampini       /* coarse discrete gradient */
13581e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13591e0482f5SStefano Zampini         PetscInt cols[2];
13601e0482f5SStefano Zampini 
13611e0482f5SStefano Zampini         cols[0] = 2*i;
13621e0482f5SStefano Zampini         cols[1] = 2*i+1;
13631e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13641e0482f5SStefano Zampini       }
1365a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1366a13144ffSStefano Zampini     }
1367a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1368a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13691e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1370a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1371a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1372a13144ffSStefano Zampini   }
1373213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1374a13144ffSStefano Zampini 
1375a13144ffSStefano Zampini   /* Start assembling */
1376a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13771e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13781e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13791e0482f5SStefano Zampini   }
1380a13144ffSStefano Zampini 
1381a13144ffSStefano Zampini   /* Free */
1382c2151214SStefano Zampini   if (fl2g) {
1383c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1384c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1385c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1386c2151214SStefano Zampini     }
1387c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1388c2151214SStefano Zampini   }
1389eee23b56SStefano Zampini 
1390eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1391eee23b56SStefano Zampini   {
1392eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1393eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1394eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1395eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1396eee23b56SStefano Zampini 
1397eee23b56SStefano Zampini     /* find first primal edge */
1398eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1399eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1400eee23b56SStefano Zampini     } else {
1401eee23b56SStefano Zampini       if (fl2g) {
1402eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1403eee23b56SStefano Zampini       }
1404eee23b56SStefano Zampini       idxs = cedges;
1405eee23b56SStefano Zampini     }
1406eee23b56SStefano Zampini     cum = 0;
1407eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1408eee23b56SStefano Zampini 
1409eee23b56SStefano Zampini     /* adapt connected components */
1410eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1411eee23b56SStefano Zampini     graph->cptr[0] = 0;
1412eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1413eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1414eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1415eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1416eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1417eee23b56SStefano Zampini         ncc++;
1418eee23b56SStefano Zampini         lc--;
1419eee23b56SStefano Zampini         cum++;
1420eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1421eee23b56SStefano Zampini       }
1422eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1423eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1424eee23b56SStefano Zampini       ncc++;
1425eee23b56SStefano Zampini     }
1426eee23b56SStefano Zampini     graph->ncc = ncc;
1427eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1428eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1429eee23b56SStefano Zampini     }
1430eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1431eee23b56SStefano Zampini   }
1432213b8bfaSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1433c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1434c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1435213b8bfaSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1436eee23b56SStefano Zampini 
1437c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1438a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1439a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1440b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1441b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1442a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1443a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1444a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1445a13144ffSStefano Zampini 
1446a13144ffSStefano Zampini   /* Complete assembling */
1447a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14481e0482f5SStefano Zampini   if (pcbddc->nedcG) {
14491e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14501e0482f5SStefano Zampini #if 0
14511e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14521e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14531e0482f5SStefano Zampini #endif
14541e0482f5SStefano Zampini   }
1455a13144ffSStefano Zampini 
1456a13144ffSStefano Zampini   /* set change of basis */
1457213b8bfaSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,singular);CHKERRQ(ierr);
1458a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1459a13144ffSStefano Zampini 
1460a13144ffSStefano Zampini   PetscFunctionReturn(0);
1461a13144ffSStefano Zampini }
1462a13144ffSStefano Zampini 
1463d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1464d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1465d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1466d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1467d8203eabSStefano Zampini {
1468d8203eabSStefano Zampini   PetscErrorCode ierr;
1469d8203eabSStefano Zampini   PetscInt       i;
1470d8203eabSStefano Zampini 
1471d8203eabSStefano Zampini   PetscFunctionBegin;
1472d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1473d8203eabSStefano Zampini     PetscInt first,last;
1474d8203eabSStefano Zampini 
1475d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
147686fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1477d8203eabSStefano Zampini     if (i>=first && i < last) {
1478d8203eabSStefano Zampini       PetscScalar *data;
1479d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1480d8203eabSStefano Zampini       if (!has_const) {
1481d8203eabSStefano Zampini         data[i-first] = 1.;
1482d8203eabSStefano Zampini       } else {
148386fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
148486fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1485d8203eabSStefano Zampini       }
1486d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1487d8203eabSStefano Zampini     }
1488d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1489d8203eabSStefano Zampini   }
1490d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1491d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1492d8203eabSStefano Zampini     PetscInt first,last;
1493ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
1494d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1495d8203eabSStefano Zampini     if (i>=first && i < last) {
1496d8203eabSStefano Zampini       PetscScalar *data;
1497d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1498d8203eabSStefano Zampini       if (!has_const) {
1499d8203eabSStefano Zampini         data[i-first] = 0.;
1500d8203eabSStefano Zampini       } else {
150186fa73c5SStefano Zampini         data[2*i-first] = 0.;
150286fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1503d8203eabSStefano Zampini       }
1504d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1505d8203eabSStefano Zampini     }
1506d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1507ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1508d8203eabSStefano Zampini   }
1509d8203eabSStefano Zampini   PetscFunctionReturn(0);
1510d8203eabSStefano Zampini }
1511d8203eabSStefano Zampini 
15128ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1513669cc0f4SStefano Zampini {
1514a198735bSStefano Zampini   Mat                    loc_divudotp;
1515fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
15168ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1517669cc0f4SStefano Zampini   IS                     *faces,*edges;
1518669cc0f4SStefano Zampini   PetscScalar            *vals;
1519669cc0f4SStefano Zampini   const PetscScalar      *array;
1520669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
15211ae86dd6SStefano Zampini   PetscMPIInt            rank;
1522a198735bSStefano Zampini   PetscErrorCode         ierr;
1523669cc0f4SStefano Zampini 
1524669cc0f4SStefano Zampini   PetscFunctionBegin;
1525669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1526669cc0f4SStefano Zampini   if (graph->twodim) {
1527669cc0f4SStefano Zampini     lmaxneighs = 2;
1528669cc0f4SStefano Zampini   } else {
1529669cc0f4SStefano Zampini     lmaxneighs = 1;
1530669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1531669cc0f4SStefano Zampini       const PetscInt *idxs;
1532669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1533669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1534669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1535669cc0f4SStefano Zampini     }
1536669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1537669cc0f4SStefano Zampini   }
1538669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1539669cc0f4SStefano Zampini   maxsize = 0;
1540669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1541669cc0f4SStefano Zampini     PetscInt nn;
1542669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1544669cc0f4SStefano Zampini   }
1545669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1546669cc0f4SStefano Zampini     PetscInt nn;
1547669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1548669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1549669cc0f4SStefano Zampini   }
1550669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1551669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1552669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
15538ae0ca82SStefano Zampini   if (!transpose) {
15548ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
15558ae0ca82SStefano Zampini   } else {
15568ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
15578ae0ca82SStefano Zampini   }
1558669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
15591ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1560d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1561669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1562ddc40e2cSstefano_zampini     ierr = VecLockPop(quad_vecs[i]);CHKERRQ(ierr);
15638ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1564669cc0f4SStefano Zampini   }
1565d8203eabSStefano Zampini 
1566669cc0f4SStefano Zampini   /* compute local quad vec */
1567a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15688ae0ca82SStefano Zampini   if (!transpose) {
1569a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15708ae0ca82SStefano Zampini   } else {
15718ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15728ae0ca82SStefano Zampini   }
1573669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15748ae0ca82SStefano Zampini   if (!transpose) {
1575a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15768ae0ca82SStefano Zampini   } else {
15778ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15788ae0ca82SStefano Zampini   }
1579fa23a32eSStefano Zampini   if (vl2l) {
1580187c917aSStefano Zampini     Mat        lA;
1581187c917aSStefano Zampini     VecScatter sc;
1582187c917aSStefano Zampini 
1583187c917aSStefano Zampini     ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1584187c917aSStefano Zampini     ierr = MatCreateVecs(lA,&vins,NULL);CHKERRQ(ierr);
1585187c917aSStefano Zampini     ierr = VecScatterCreate(v,vl2l,vins,NULL,&sc);CHKERRQ(ierr);
1586187c917aSStefano Zampini     ierr = VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1587187c917aSStefano Zampini     ierr = VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1588187c917aSStefano Zampini     ierr = VecScatterDestroy(&sc);CHKERRQ(ierr);
1589fa23a32eSStefano Zampini   } else {
1590fa23a32eSStefano Zampini     vins = v;
1591fa23a32eSStefano Zampini   }
1592fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1593669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15949a962809SStefano Zampini 
15951ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15961ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1597669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1598669cc0f4SStefano Zampini     const PetscInt    *idxs;
1599669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1600669cc0f4SStefano Zampini 
1601669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1602669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1603669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
16041ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1605669cc0f4SStefano Zampini     idx  = -(idx+1);
1606669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1607669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1608669cc0f4SStefano Zampini   }
1609669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1610669cc0f4SStefano Zampini     const PetscInt    *idxs;
1611669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1612669cc0f4SStefano Zampini 
1613669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1614669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1615669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
16161ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1617669cc0f4SStefano Zampini     idx  = -(idx+1);
1618669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1619669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1620669cc0f4SStefano Zampini   }
1621c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1622fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1623fa23a32eSStefano Zampini   if (vl2l) {
1624187c917aSStefano Zampini     ierr = VecDestroy(&vins);CHKERRQ(ierr);
1625fa23a32eSStefano Zampini   }
1626669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1627669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1628669cc0f4SStefano Zampini 
1629669cc0f4SStefano Zampini   /* assemble near null space */
1630669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1631669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1632669cc0f4SStefano Zampini   }
1633669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1634669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1635ddc40e2cSstefano_zampini     ierr = VecLockPush(quad_vecs[i]);CHKERRQ(ierr);
1636669cc0f4SStefano Zampini   }
1637669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1638669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1639669cc0f4SStefano Zampini }
1640669cc0f4SStefano Zampini 
16417620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
16427620a527SStefano Zampini {
16437620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16447620a527SStefano Zampini   PetscErrorCode ierr;
16457620a527SStefano Zampini 
16467620a527SStefano Zampini   PetscFunctionBegin;
16477620a527SStefano Zampini   if (primalv) {
16487620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
16497620a527SStefano Zampini       IS list[2], newp;
16507620a527SStefano Zampini 
16517620a527SStefano Zampini       list[0] = primalv;
16527620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
16537620a527SStefano Zampini       ierr = ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp);CHKERRQ(ierr);
16547620a527SStefano Zampini       ierr = ISSortRemoveDups(newp);CHKERRQ(ierr);
16557620a527SStefano Zampini       ierr = ISDestroy(&list[1]);CHKERRQ(ierr);
16567620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
16577620a527SStefano Zampini     } else {
16587620a527SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
16597620a527SStefano Zampini     }
16607620a527SStefano Zampini   }
16617620a527SStefano Zampini   PetscFunctionReturn(0);
16627620a527SStefano Zampini }
1663669cc0f4SStefano Zampini 
16641f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
16651f4df5f7SStefano Zampini {
16661f4df5f7SStefano Zampini   PetscErrorCode ierr;
16671f4df5f7SStefano Zampini   Vec            local,global;
16681f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16691f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
16705c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
16711f4df5f7SStefano Zampini 
16721f4df5f7SStefano Zampini   PetscFunctionBegin;
16735c5e10d6SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr);
16745c5e10d6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL);CHKERRQ(ierr);
16755c5e10d6SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
16761f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
167721ef3d20SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16781f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16795c5e10d6SStefano Zampini   if (monolithic) goto boundary;
16805c5e10d6SStefano Zampini 
16811f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16821f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16831f4df5f7SStefano Zampini       PetscInt i;
16841f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16851f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16861f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16871f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16881f4df5f7SStefano Zampini       }
16891f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16901f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16911f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16921f4df5f7SStefano Zampini     }
16931f4df5f7SStefano Zampini   } else {
169421ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
169521ef3d20SStefano Zampini       DM dm;
169621ef3d20SStefano Zampini 
169721ef3d20SStefano Zampini       ierr = PCGetDM(pc, &dm);CHKERRQ(ierr);
169821ef3d20SStefano Zampini       if (!dm) {
169921ef3d20SStefano Zampini         ierr = MatGetDM(pc->pmat, &dm);CHKERRQ(ierr);
170021ef3d20SStefano Zampini       }
170121ef3d20SStefano Zampini       if (dm) {
170221ef3d20SStefano Zampini         IS      *fields;
170321ef3d20SStefano Zampini         PetscInt nf,i;
170421ef3d20SStefano Zampini         ierr = DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL);CHKERRQ(ierr);
170521ef3d20SStefano Zampini         ierr = PetscMalloc1(nf,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
170621ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
170721ef3d20SStefano Zampini           ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
170821ef3d20SStefano Zampini           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
170921ef3d20SStefano Zampini         }
171021ef3d20SStefano Zampini         ierr = PetscFree(fields);CHKERRQ(ierr);
171121ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
171221ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
171321ef3d20SStefano Zampini         PetscContainer   c;
171421ef3d20SStefano Zampini 
171521ef3d20SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr);
171621ef3d20SStefano Zampini         if (c) {
171721ef3d20SStefano Zampini           MatISLocalFields lf;
171821ef3d20SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr);
171921ef3d20SStefano Zampini           ierr = PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf);CHKERRQ(ierr);
172021ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
17211f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
1722986cdee1SStefano Zampini           ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
172321ef3d20SStefano Zampini           if (i > 1) {
1724986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
17251f4df5f7SStefano Zampini             ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
17261f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
17271f4df5f7SStefano Zampini               ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
17281f4df5f7SStefano Zampini             }
17291f4df5f7SStefano Zampini           }
173021ef3d20SStefano Zampini         }
173121ef3d20SStefano Zampini       }
17327a0e7b2cSstefano_zampini     } else {
17337a0e7b2cSstefano_zampini       PetscInt i;
17347a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
17357a0e7b2cSstefano_zampini         ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
17367a0e7b2cSstefano_zampini       }
17371f4df5f7SStefano Zampini     }
1738986cdee1SStefano Zampini   }
17391f4df5f7SStefano Zampini 
17405c5e10d6SStefano Zampini boundary:
17411f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
17421f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17437a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
17447a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
17451f4df5f7SStefano Zampini   }
17461f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
17471f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17487a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
17497a0e7b2cSstefano_zampini     ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
17501f4df5f7SStefano Zampini   }
17511f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
17521f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
17531f4df5f7SStefano Zampini   }
17541f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
17551f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
17567620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
17577620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
17587620a527SStefano Zampini     IS       primalv = NULL;
17597620a527SStefano Zampini     PetscInt i;
17607a0e7b2cSstefano_zampini 
17617620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17627620a527SStefano Zampini       ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
17637620a527SStefano Zampini     }
17647620a527SStefano Zampini     ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
17657620a527SStefano Zampini     ierr = PCBDDCDetectDisconnectedComponents(pc,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv);CHKERRQ(ierr);
17667620a527SStefano Zampini     ierr = PCBDDCAddPrimalVerticesLocalIS(pc,primalv);CHKERRQ(ierr);
17677620a527SStefano Zampini     ierr = ISDestroy(&primalv);CHKERRQ(ierr);
17687620a527SStefano Zampini   }
17697620a527SStefano Zampini   /* early stage corner detection */
17707620a527SStefano Zampini   {
17717620a527SStefano Zampini     DM dm;
17727620a527SStefano Zampini 
17737620a527SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
17747620a527SStefano Zampini     if (dm) {
17757620a527SStefano Zampini       PetscBool isda;
17767620a527SStefano Zampini 
17777620a527SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);CHKERRQ(ierr);
17787620a527SStefano Zampini       if (isda) {
17797620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17807620a527SStefano Zampini         IS                     corners;
17817620a527SStefano Zampini         Mat                    lA;
17827620a527SStefano Zampini 
1783d4a6ed37SStefano Zampini         ierr = DMDAGetSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17847620a527SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17857620a527SStefano Zampini         ierr = MatGetLocalToGlobalMapping(lA,&l2l,NULL);CHKERRQ(ierr);
17867620a527SStefano Zampini         ierr = MatISRestoreLocalMat(pc->pmat,&lA);CHKERRQ(ierr);
17877620a527SStefano Zampini         if (l2l) {
17887620a527SStefano Zampini           const PetscInt *idx;
17897620a527SStefano Zampini           PetscInt       bs,*idxout,n;
17907620a527SStefano Zampini 
17917620a527SStefano Zampini           ierr = ISLocalToGlobalMappingGetBlockSize(l2l,&bs);CHKERRQ(ierr);
17927620a527SStefano Zampini           ierr = ISGetLocalSize(corners,&n);CHKERRQ(ierr);
17937620a527SStefano Zampini           ierr = ISGetIndices(corners,&idx);CHKERRQ(ierr);
17947620a527SStefano Zampini           ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
17957620a527SStefano Zampini           ierr = ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout);CHKERRQ(ierr);
17967620a527SStefano Zampini           ierr = ISRestoreIndices(corners,&idx);CHKERRQ(ierr);
1797d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
17987620a527SStefano Zampini           ierr = ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners);CHKERRQ(ierr);
17997620a527SStefano Zampini           ierr = PCBDDCAddPrimalVerticesLocalIS(pc,corners);CHKERRQ(ierr);
18007620a527SStefano Zampini           ierr = ISDestroy(&corners);CHKERRQ(ierr);
18017620a527SStefano Zampini         } else { /* not from DMDA */
1802d4a6ed37SStefano Zampini           ierr = DMDARestoreSubdomainCornersIS(dm,&corners);CHKERRQ(ierr);
18037620a527SStefano Zampini         }
18047620a527SStefano Zampini       }
18057620a527SStefano Zampini     }
18067620a527SStefano Zampini   }
18077a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18087a0e7b2cSstefano_zampini }
18097a0e7b2cSstefano_zampini 
18107a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18117a0e7b2cSstefano_zampini {
18127a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18137a0e7b2cSstefano_zampini   PetscErrorCode  ierr;
18147a0e7b2cSstefano_zampini   IS              nis;
18157a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18167a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18177a0e7b2cSstefano_zampini   PetscBool       *ld;
18187a0e7b2cSstefano_zampini 
18197a0e7b2cSstefano_zampini   PetscFunctionBegin;
18207a0e7b2cSstefano_zampini   if (mop != MPI_LAND && mop != MPI_LOR) SETERRQ(PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18217a0e7b2cSstefano_zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
18227a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18237a0e7b2cSstefano_zampini     /* init rootdata with true */
18247a0e7b2cSstefano_zampini     ld   = (PetscBool*) matis->sf_rootdata;
18257a0e7b2cSstefano_zampini     for (i=0;i<pc->pmat->rmap->n;i++) ld[i] = PETSC_TRUE;
18267a0e7b2cSstefano_zampini   } else {
18277a0e7b2cSstefano_zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscBool));CHKERRQ(ierr);
18287a0e7b2cSstefano_zampini   }
18297a0e7b2cSstefano_zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscBool));CHKERRQ(ierr);
18307a0e7b2cSstefano_zampini   ierr = ISGetLocalSize(*is,&nd);CHKERRQ(ierr);
18317a0e7b2cSstefano_zampini   ierr = ISGetIndices(*is,&idxs);CHKERRQ(ierr);
18327a0e7b2cSstefano_zampini   ld   = (PetscBool*) matis->sf_leafdata;
18337a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18347a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18357a0e7b2cSstefano_zampini       ld[idxs[i]] = PETSC_TRUE;
18367a0e7b2cSstefano_zampini   ierr = ISRestoreIndices(*is,&idxs);CHKERRQ(ierr);
18377a0e7b2cSstefano_zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18387a0e7b2cSstefano_zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_BOOL,matis->sf_leafdata,matis->sf_rootdata,mop);CHKERRQ(ierr);
18397a0e7b2cSstefano_zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18407a0e7b2cSstefano_zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_BOOL,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18417a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18427a0e7b2cSstefano_zampini     ierr = PetscMalloc1(nd,&nidxs);CHKERRQ(ierr);
18437a0e7b2cSstefano_zampini   } else {
18447a0e7b2cSstefano_zampini     ierr = PetscMalloc1(n,&nidxs);CHKERRQ(ierr);
18457a0e7b2cSstefano_zampini   }
18467a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18477a0e7b2cSstefano_zampini     if (ld[i])
18487a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18497a0e7b2cSstefano_zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis);CHKERRQ(ierr);
18507a0e7b2cSstefano_zampini   ierr = ISDestroy(is);CHKERRQ(ierr);
18517a0e7b2cSstefano_zampini   *is  = nis;
18521f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18531f4df5f7SStefano Zampini }
18541f4df5f7SStefano Zampini 
18553e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
18563e589ea0SStefano Zampini {
18573e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
18583e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
18593e589ea0SStefano Zampini   PetscErrorCode    ierr;
18603e589ea0SStefano Zampini 
18613e589ea0SStefano Zampini   PetscFunctionBegin;
18623e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
18633e589ea0SStefano Zampini     PetscFunctionReturn(0);
18643e589ea0SStefano Zampini   }
18653e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18663e589ea0SStefano Zampini     Vec swap;
18673e589ea0SStefano Zampini 
18683e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18693e589ea0SStefano Zampini     swap = pcbddc->work_change;
18703e589ea0SStefano Zampini     pcbddc->work_change = r;
18713e589ea0SStefano Zampini     r = swap;
18723e589ea0SStefano Zampini   }
18733e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18743e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18753e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18763e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
18773e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18783e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18793e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1880f913dca9SStefano Zampini     pcbddc->work_change = r;
18813e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18823e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18833e589ea0SStefano Zampini   }
18843e589ea0SStefano Zampini   PetscFunctionReturn(0);
18853e589ea0SStefano Zampini }
18863e589ea0SStefano Zampini 
1887a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1888a3df083aSStefano Zampini {
1889a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1890a3df083aSStefano Zampini   PetscErrorCode          ierr;
1891a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1892a3df083aSStefano Zampini 
1893a3df083aSStefano Zampini   PetscFunctionBegin;
1894a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1895a3df083aSStefano Zampini   if (transpose) {
1896a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1897a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1898a3df083aSStefano Zampini   } else {
1899a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1900a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1901a3df083aSStefano Zampini   }
1902a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1903a3df083aSStefano Zampini   if (apply_right) {
1904a3df083aSStefano Zampini     const PetscScalar *ax;
1905a3df083aSStefano Zampini     PetscInt          nl,i;
1906a3df083aSStefano Zampini 
1907a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1908a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1909a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1910a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1911a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1912a3df083aSStefano Zampini       PetscScalar    sum,val;
1913a3df083aSStefano Zampini       const PetscInt *idxs;
1914a3df083aSStefano Zampini       PetscInt       nz,j;
1915a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1916a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1917a3df083aSStefano Zampini       sum = 0.;
1918a3df083aSStefano Zampini       if (ctx->apply_p0) {
1919a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1920a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1921a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1922a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1923a3df083aSStefano Zampini         }
1924a3df083aSStefano Zampini       } else {
1925a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1926a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1927a3df083aSStefano Zampini         }
1928a3df083aSStefano Zampini       }
1929a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1930a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1931a3df083aSStefano Zampini     }
1932a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1933a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1934a3df083aSStefano Zampini   }
1935a3df083aSStefano Zampini   if (transpose) {
1936a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1937a3df083aSStefano Zampini   } else {
1938a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1939a3df083aSStefano Zampini   }
1940a3df083aSStefano Zampini   if (reset_x) {
1941a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1942a3df083aSStefano Zampini   }
1943a3df083aSStefano Zampini   if (apply_left) {
1944a3df083aSStefano Zampini     PetscScalar *ay;
1945a3df083aSStefano Zampini     PetscInt    i;
1946a3df083aSStefano Zampini 
1947a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1948a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1949a3df083aSStefano Zampini       PetscScalar    sum,val;
1950a3df083aSStefano Zampini       const PetscInt *idxs;
1951a3df083aSStefano Zampini       PetscInt       nz,j;
1952a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1953a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1954a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1955a3df083aSStefano Zampini       if (ctx->apply_p0) {
1956a3df083aSStefano Zampini         sum = 0.;
1957a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1958a3df083aSStefano Zampini           sum += ay[idxs[j]];
1959a3df083aSStefano Zampini           ay[idxs[j]] += val;
1960a3df083aSStefano Zampini         }
1961a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1962a3df083aSStefano Zampini       } else {
1963a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1964a3df083aSStefano Zampini           ay[idxs[j]] += val;
1965a3df083aSStefano Zampini         }
1966a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1967a3df083aSStefano Zampini       }
1968a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1969a3df083aSStefano Zampini     }
1970a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1971a3df083aSStefano Zampini   }
1972a3df083aSStefano Zampini   PetscFunctionReturn(0);
1973a3df083aSStefano Zampini }
1974a3df083aSStefano Zampini 
1975a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1976a3df083aSStefano Zampini {
1977a3df083aSStefano Zampini   PetscErrorCode ierr;
1978a3df083aSStefano Zampini 
1979a3df083aSStefano Zampini   PetscFunctionBegin;
1980a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1981a3df083aSStefano Zampini   PetscFunctionReturn(0);
1982a3df083aSStefano Zampini }
1983a3df083aSStefano Zampini 
1984a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1985a3df083aSStefano Zampini {
1986a3df083aSStefano Zampini   PetscErrorCode ierr;
1987a3df083aSStefano Zampini 
1988a3df083aSStefano Zampini   PetscFunctionBegin;
1989a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1990a3df083aSStefano Zampini   PetscFunctionReturn(0);
1991a3df083aSStefano Zampini }
1992a3df083aSStefano Zampini 
1993a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1994a3df083aSStefano Zampini {
1995a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1996a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1997a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1998a3df083aSStefano Zampini   PetscErrorCode          ierr;
1999a3df083aSStefano Zampini 
2000a3df083aSStefano Zampini   PetscFunctionBegin;
2001a3df083aSStefano Zampini   if (!restore) {
20021dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2003a3df083aSStefano Zampini     PetscScalar        *work;
2004b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2005a3df083aSStefano Zampini 
20069a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20079a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
2008a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
2009a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
2010a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2011a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
2012a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
2013a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
2014a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
2015a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
2016a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2017a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2018a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2019a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2020059032f7SStefano Zampini     if (reuse) {
2021a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20221dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2023059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2024059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2025059032f7SStefano Zampini       PetscInt               i;
2026059032f7SStefano Zampini 
2027059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
2028059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2029059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2030059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2031059032f7SStefano Zampini       }
2032059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
20331dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2034059032f7SStefano Zampini     }
2035a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2036a3df083aSStefano Zampini     ctx->work = work;
2037a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
2038a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2039a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2040a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2041a3df083aSStefano Zampini 
2042a3df083aSStefano Zampini     /* A_BI as A_IB^T */
2043a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
2044a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2045a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2046a3df083aSStefano Zampini   } else {
20471dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20481dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20491dd7afcfSStefano Zampini     }
2050a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
2051a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
2052a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20531dd7afcfSStefano Zampini     ctx->A = NULL;
20541dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
20551dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20561dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20571dd7afcfSStefano Zampini     if (ctx->free) {
2058059032f7SStefano Zampini       PetscInt i;
20591dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
2060059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2061059032f7SStefano Zampini       }
2062059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
2063059032f7SStefano Zampini     }
2064a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
2065a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
2066a3df083aSStefano Zampini   }
2067a3df083aSStefano Zampini   PetscFunctionReturn(0);
2068a3df083aSStefano Zampini }
2069a3df083aSStefano Zampini 
2070a3df083aSStefano Zampini /* used just in bddc debug mode */
2071a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2072a3df083aSStefano Zampini {
2073a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2074a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2075a3df083aSStefano Zampini   Mat            An;
2076a3df083aSStefano Zampini   PetscErrorCode ierr;
2077a3df083aSStefano Zampini 
2078a3df083aSStefano Zampini   PetscFunctionBegin;
2079a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
2080a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
2081a3df083aSStefano Zampini   if (is1) {
20827dae84e0SHong Zhang     ierr = MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
2083a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
2084a3df083aSStefano Zampini   } else {
2085a3df083aSStefano Zampini     *B = An;
2086a3df083aSStefano Zampini   }
2087a3df083aSStefano Zampini   PetscFunctionReturn(0);
2088a3df083aSStefano Zampini }
2089a3df083aSStefano Zampini 
20901cf9b237SStefano Zampini /* TODO: add reuse flag */
20911cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
20921cf9b237SStefano Zampini {
20931cf9b237SStefano Zampini   Mat            Bt;
20941cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
20951cf9b237SStefano Zampini   const PetscInt *ii,*ij;
20961cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
20971cf9b237SStefano Zampini   PetscBool      flg_row;
20981cf9b237SStefano Zampini   PetscErrorCode ierr;
20991cf9b237SStefano Zampini 
21001cf9b237SStefano Zampini   PetscFunctionBegin;
21011cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
21021cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21031cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
21041cf9b237SStefano Zampini   nnz = n;
21051cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21061cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21071cf9b237SStefano Zampini   }
21081cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
21091cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
21101cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
21111cf9b237SStefano Zampini   nnz = 0;
21121cf9b237SStefano Zampini   bii[0] = 0;
21131cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21141cf9b237SStefano Zampini     PetscInt j;
21151cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21161cf9b237SStefano Zampini       PetscScalar entry = a[j];
21171cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
21181cf9b237SStefano Zampini         bij[nnz] = ij[j];
21191cf9b237SStefano Zampini         bdata[nnz] = entry;
21201cf9b237SStefano Zampini         nnz++;
21211cf9b237SStefano Zampini       }
21221cf9b237SStefano Zampini     }
21231cf9b237SStefano Zampini     bii[i+1] = nnz;
21241cf9b237SStefano Zampini   }
21251cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
21261cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
21271cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
21281cf9b237SStefano Zampini   {
21291cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21301cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21311cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21321cf9b237SStefano Zampini   }
21331cf9b237SStefano Zampini   *B = Bt;
21341cf9b237SStefano Zampini   PetscFunctionReturn(0);
21351cf9b237SStefano Zampini }
21361cf9b237SStefano Zampini 
2137c80a6c00SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscInt *ncc, IS* cc[], IS* primalv)
21384f1b2e48SStefano Zampini {
2139c80a6c00SStefano Zampini   Mat                    B = NULL;
2140c80a6c00SStefano Zampini   DM                     dm;
21414f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21424f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21434f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2144c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21454f1b2e48SStefano Zampini   PetscInt               i,n;
21464f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2147c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21484f1b2e48SStefano Zampini   PetscErrorCode         ierr;
21494f1b2e48SStefano Zampini 
21504f1b2e48SStefano Zampini   PetscFunctionBegin;
2151a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2152a2eca866SStefano Zampini   if (cc) *cc = NULL;
2153a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
2154c80a6c00SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2155c80a6c00SStefano Zampini   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2156c80a6c00SStefano Zampini   if (!dm) {
2157c80a6c00SStefano Zampini     ierr = MatGetDM(pc->pmat,&dm);CHKERRQ(ierr);
2158c80a6c00SStefano Zampini   }
2159c80a6c00SStefano Zampini   if (dm) {
2160c80a6c00SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
2161c80a6c00SStefano Zampini   }
2162c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2163c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2164c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2165c80a6c00SStefano Zampini     IS             cellNumbering;
2166c80a6c00SStefano Zampini     const PetscInt *cellNum;
2167c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2168c80a6c00SStefano Zampini     PetscSection   section;
2169c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2170c80a6c00SStefano Zampini     PetscSF        sfPoint;
2171c80a6c00SStefano Zampini     PetscErrorCode ierr;
2172c80a6c00SStefano Zampini 
2173c80a6c00SStefano Zampini     PetscFunctionBegin;
2174c80a6c00SStefano Zampini     ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
2175c80a6c00SStefano Zampini     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
2176c80a6c00SStefano Zampini     ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2177c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
2178c80a6c00SStefano Zampini     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
2179c80a6c00SStefano Zampini     ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
2180c80a6c00SStefano Zampini     ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
2181c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
2182c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
2183c80a6c00SStefano Zampini     ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
2184c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr);
2185c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr);
2186956e2312SStefano Zampini     ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr);
2187c80a6c00SStefano Zampini     ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
2188c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2189c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2190c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2191c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
2192c80a6c00SStefano Zampini       ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
2193c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2194c80a6c00SStefano Zampini         const PetscInt point = adj[a];
21955cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2196c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
2197c80a6c00SStefano Zampini           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2198c80a6c00SStefano Zampini           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2199c80a6c00SStefano Zampini           *pBuf = point;
2200c80a6c00SStefano Zampini         }
2201c80a6c00SStefano Zampini       }
2202c80a6c00SStefano Zampini       n++;
2203c80a6c00SStefano Zampini     }
2204c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr);
2205c80a6c00SStefano Zampini     ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr);
2206c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
2207c80a6c00SStefano Zampini     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2208c80a6c00SStefano Zampini     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2209c80a6c00SStefano Zampini     ierr = PetscMalloc1(n+1, &xadj);CHKERRQ(ierr);
2210c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2211c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2212c80a6c00SStefano Zampini       ierr = PetscSectionGetOffset(section, p, &(xadj[idx++]));CHKERRQ(ierr);
2213c80a6c00SStefano Zampini     }
2214c80a6c00SStefano Zampini     xadj[n] = size;
2215c80a6c00SStefano Zampini     ierr = PetscSegBufferExtractAlloc(adjBuffer, &adjncy);CHKERRQ(ierr);
2216c80a6c00SStefano Zampini     /* Clean up */
2217c80a6c00SStefano Zampini     ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
2218c80a6c00SStefano Zampini     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
2219c80a6c00SStefano Zampini     ierr = PetscFree(adj);CHKERRQ(ierr);
2220c80a6c00SStefano Zampini     graph->xadj = xadj;
2221c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2222c80a6c00SStefano Zampini   } else {
2223c80a6c00SStefano Zampini     Mat       A;
2224c80a6c00SStefano Zampini     PetscBool filter = PETSC_FALSE, isseqaij, flg_row;
2225c80a6c00SStefano Zampini 
2226c80a6c00SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
222763c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
2228a2eca866SStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
222963c961adSStefano Zampini       PetscFunctionReturn(0);
223063c961adSStefano Zampini     }
22314f1b2e48SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
22324f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22331cf9b237SStefano Zampini       PetscBool isseqdense;
22341cf9b237SStefano Zampini 
22351cf9b237SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
22361cf9b237SStefano Zampini       if (!isseqdense) {
22374f1b2e48SStefano Zampini         ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
22381cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22391cf9b237SStefano Zampini         PetscScalar *array;
22401cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22411cf9b237SStefano Zampini 
22421cf9b237SStefano Zampini         ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
22431cf9b237SStefano Zampini         ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
22441cf9b237SStefano Zampini         ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
22451cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22461cf9b237SStefano Zampini           PetscInt j;
22471cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22481cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22491cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22501cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22511cf9b237SStefano Zampini           }
22521cf9b237SStefano Zampini         }
22531cf9b237SStefano Zampini         ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
22549d54b7f4SStefano Zampini         ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
22551cf9b237SStefano Zampini       }
22564f1b2e48SStefano Zampini     } else {
2257c80a6c00SStefano Zampini       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
22584f1b2e48SStefano Zampini       B = A;
22594f1b2e48SStefano Zampini     }
22604f1b2e48SStefano Zampini     ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
22614f1b2e48SStefano Zampini 
22624f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
22634f1b2e48SStefano Zampini     if (filter) {
22644f1b2e48SStefano Zampini       PetscScalar *data;
22654f1b2e48SStefano Zampini       PetscInt    j,cum;
22664f1b2e48SStefano Zampini 
22674f1b2e48SStefano Zampini       ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
22684f1b2e48SStefano Zampini       ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
22694f1b2e48SStefano Zampini       cum = 0;
22704f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
22714f1b2e48SStefano Zampini         PetscInt t;
22724f1b2e48SStefano Zampini 
22734f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
22744f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
22754f1b2e48SStefano Zampini             continue;
22764f1b2e48SStefano Zampini           }
22774f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
22784f1b2e48SStefano Zampini         }
22794f1b2e48SStefano Zampini         t = xadj_filtered[i];
22804f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
22814f1b2e48SStefano Zampini         cum += t;
22824f1b2e48SStefano Zampini       }
22834f1b2e48SStefano Zampini       ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
22844f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
22854f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
22864f1b2e48SStefano Zampini     } else {
22874f1b2e48SStefano Zampini       graph->xadj = xadj;
22884f1b2e48SStefano Zampini       graph->adjncy = adjncy;
22894f1b2e48SStefano Zampini     }
2290c80a6c00SStefano Zampini   }
2291c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
2292c80a6c00SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
2293c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
2294c80a6c00SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2295c80a6c00SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
2296c80a6c00SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
22974f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
22984f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
2299c80a6c00SStefano Zampini 
23004f1b2e48SStefano Zampini   /* partial clean up */
23014f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
2302c80a6c00SStefano Zampini   if (B) {
2303c80a6c00SStefano Zampini     PetscBool flg_row;
23044f1b2e48SStefano Zampini     ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
23054f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
23064f1b2e48SStefano Zampini   }
2307c80a6c00SStefano Zampini   if (isplex) {
2308c80a6c00SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2309c80a6c00SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2310c80a6c00SStefano Zampini   }
23114f1b2e48SStefano Zampini 
23124f1b2e48SStefano Zampini   /* get back data */
2313c80a6c00SStefano Zampini   if (isplex) {
2314c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2315c80a6c00SStefano Zampini     if (cc || primalv) {
2316c80a6c00SStefano Zampini       Mat          A;
2317c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2318c80a6c00SStefano Zampini       PetscSection subSection;
2319c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2320c80a6c00SStefano Zampini 
2321c80a6c00SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm,&subSection);CHKERRQ(ierr);
2322c80a6c00SStefano Zampini       ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
2323c80a6c00SStefano Zampini       ierr = PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids);CHKERRQ(ierr);
2324c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btv);CHKERRQ(ierr);
2325c80a6c00SStefano Zampini       ierr = PetscBTCreate(A->rmap->n,&btvt);CHKERRQ(ierr);
2326c80a6c00SStefano Zampini 
2327c80a6c00SStefano Zampini       cids[0] = 0;
2328c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2329c80a6c00SStefano Zampini         PetscInt j;
2330c80a6c00SStefano Zampini 
2331c80a6c00SStefano Zampini         ierr = PetscBTMemzero(A->rmap->n,btvt);CHKERRQ(ierr);
2332c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2333c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2334c80a6c00SStefano Zampini 
2335c80a6c00SStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2336c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
2337c80a6c00SStefano Zampini             PetscInt s, p = closure[k], off, dof, cdof;
2338c80a6c00SStefano Zampini 
2339c80a6c00SStefano Zampini             ierr = PetscSectionGetConstraintDof(subSection, p, &cdof);CHKERRQ(ierr);
2340c80a6c00SStefano Zampini             ierr = PetscSectionGetOffset(subSection,p,&off);CHKERRQ(ierr);
2341c80a6c00SStefano Zampini             ierr = PetscSectionGetDof(subSection,p,&dof);CHKERRQ(ierr);
2342c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2343c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2344c80a6c00SStefano Zampini               if (!PetscBTLookup(btv,off+s)) {
2345c80a6c00SStefano Zampini                 ids[cum++] = off+s;
2346c80a6c00SStefano Zampini               } else { /* cross-vertex */
2347c80a6c00SStefano Zampini                 pids[cump++] = off+s;
2348c80a6c00SStefano Zampini               }
2349c80a6c00SStefano Zampini             }
2350c80a6c00SStefano Zampini           }
2351c80a6c00SStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure);CHKERRQ(ierr);
2352c80a6c00SStefano Zampini         }
2353c80a6c00SStefano Zampini         cids[i+1] = cum;
2354c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2355c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
2356c80a6c00SStefano Zampini           ierr = PetscBTSet(btv,ids[j]);CHKERRQ(ierr);
2357c80a6c00SStefano Zampini         }
2358c80a6c00SStefano Zampini       }
2359c80a6c00SStefano Zampini       if (cc) {
2360c80a6c00SStefano Zampini         ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
2361c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
2362c80a6c00SStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
2363c80a6c00SStefano Zampini         }
2364c80a6c00SStefano Zampini         *cc = cc_n;
2365c80a6c00SStefano Zampini       }
2366c80a6c00SStefano Zampini       if (primalv) {
2367c80a6c00SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv);CHKERRQ(ierr);
2368c80a6c00SStefano Zampini       }
2369c80a6c00SStefano Zampini       ierr = PetscFree3(ids,cids,pids);CHKERRQ(ierr);
2370c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
2371c80a6c00SStefano Zampini       ierr = PetscBTDestroy(&btvt);CHKERRQ(ierr);
2372c80a6c00SStefano Zampini     }
2373c80a6c00SStefano Zampini   } else {
23741cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
23751cf9b237SStefano Zampini     if (cc) {
23764f1b2e48SStefano Zampini       ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
23774f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
23784f1b2e48SStefano 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);
23794f1b2e48SStefano Zampini       }
23804f1b2e48SStefano Zampini       *cc = cc_n;
23811cf9b237SStefano Zampini     }
2382c80a6c00SStefano Zampini   }
23834f1b2e48SStefano Zampini   /* clean up graph */
23844f1b2e48SStefano Zampini   graph->xadj = 0;
23854f1b2e48SStefano Zampini   graph->adjncy = 0;
23864f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
23874f1b2e48SStefano Zampini   PetscFunctionReturn(0);
23884f1b2e48SStefano Zampini }
23894f1b2e48SStefano Zampini 
23905408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
23915408967cSStefano Zampini {
23925408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
23935408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2394dee84bffSStefano Zampini   IS             dirIS = NULL;
23954f1b2e48SStefano Zampini   PetscInt       i;
23965408967cSStefano Zampini   PetscErrorCode ierr;
23975408967cSStefano Zampini 
23985408967cSStefano Zampini   PetscFunctionBegin;
2399dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
24005408967cSStefano Zampini   if (zerodiag) {
24015408967cSStefano Zampini     Mat            A;
24025408967cSStefano Zampini     Vec            vec3_N;
24035408967cSStefano Zampini     PetscScalar    *vals;
24045408967cSStefano Zampini     const PetscInt *idxs;
2405d12d3064SStefano Zampini     PetscInt       nz,*count;
24065408967cSStefano Zampini 
24075408967cSStefano Zampini     /* p0 */
24085408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
24095408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
24105408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24115408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24124f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24135408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24145408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
24155408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
24165408967cSStefano Zampini     /* v_I */
24175408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
24185408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24195408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24205408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
24215408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24225408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24235408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24245408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
24255408967cSStefano Zampini     if (dirIS) {
24265408967cSStefano Zampini       PetscInt n;
24275408967cSStefano Zampini 
24285408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
24295408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
24305408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24315408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
24325408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
24335408967cSStefano Zampini     }
24345408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
24355408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
24365408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
24375408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2438669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24395408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
24405408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
24419a962809SStefano 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]));
24425408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
24435408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2444d12d3064SStefano Zampini 
2445d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2446d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2447d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2448d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2449d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2450d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
24519a962809SStefano 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]);
2452d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2453d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
24545408967cSStefano Zampini   }
2455dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
24565408967cSStefano Zampini 
24575408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
24585408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
24594f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
24605408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
24614f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
24625408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2463f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2464f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
246513903a91SSatish Balay     if (val != -PetscGlobalRank-i) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %d instead of %g\n",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i);
2466f2a566d8SStefano Zampini   }
24675408967cSStefano Zampini   PetscFunctionReturn(0);
24685408967cSStefano Zampini }
24695408967cSStefano Zampini 
2470339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2471339f8db1SStefano Zampini {
2472339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24734edc6404Sstefano_zampini   IS             pressures,zerodiag,zerodiag_save,*zerodiag_subs;
2474b0f5fe93SStefano Zampini   PetscInt       nz,n;
24754edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
24764edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2477339f8db1SStefano Zampini   PetscErrorCode ierr;
2478339f8db1SStefano Zampini 
2479339f8db1SStefano Zampini   PetscFunctionBegin;
24809f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
24819f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2482a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2483a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2484a3df083aSStefano Zampini   }
2485a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2486a3df083aSStefano Zampini   pcbddc->benign_n = 0;
248728b8efb1Sstefano_zampini 
248828b8efb1Sstefano_zampini   /* if a local info on dofs is present, uses the last field for "pressures" (or fid by command line)
24894f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
24904f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
24914f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
24921ae86dd6SStefano Zampini      since the local Schur complements are already SPD
24934f1b2e48SStefano Zampini   */
24944f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
24954f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
249640fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
24977fbe2174Sstefano_zampini     IS       iP = NULL;
24984f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
24994f1b2e48SStefano Zampini 
250028b8efb1Sstefano_zampini     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr);
250128b8efb1Sstefano_zampini     ierr = PetscOptionsInt("-pc_bddc_pressure_field","Field id for pressures",NULL,p,&p,NULL);CHKERRQ(ierr);
250228b8efb1Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
250328b8efb1Sstefano_zampini     if (p < 0 || p > pcbddc->n_ISForDofsLocal-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",p);
25044f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
25054f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
25064f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
25074f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2508ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
25097fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25107fbe2174Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP);CHKERRQ(ierr);
25117fbe2174Sstefano_zampini     if (iP) {
25127fbe2174Sstefano_zampini       IS newpressures;
25137fbe2174Sstefano_zampini 
25147fbe2174Sstefano_zampini       ierr = ISDifference(pressures,iP,&newpressures);CHKERRQ(ierr);
25157fbe2174Sstefano_zampini       ierr = ISDestroy(&pressures);CHKERRQ(ierr);
25167fbe2174Sstefano_zampini       pressures = newpressures;
25177fbe2174Sstefano_zampini     }
251840fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
251940fa8d13SStefano Zampini     if (!sorted) {
252040fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
252140fa8d13SStefano Zampini     }
252240fa8d13SStefano Zampini   } else {
252340fa8d13SStefano Zampini     pressures = NULL;
252440fa8d13SStefano Zampini   }
252597d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
252697d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
252727b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
252897d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2529339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2530339f8db1SStefano Zampini   if (!sorted) {
2531339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2532339f8db1SStefano Zampini   }
25334edc6404Sstefano_zampini   ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
25344edc6404Sstefano_zampini   zerodiag_save = zerodiag;
2535339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
25364f1b2e48SStefano Zampini   if (!nz) {
25374f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
25384f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
253940fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
254040fa8d13SStefano Zampini   }
25414f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
25424f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
25434f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
25444f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
25451f4df5f7SStefano Zampini   n_interior_dofs  = 0;
25461f4df5f7SStefano Zampini   interior_dofs    = NULL;
25474edc6404Sstefano_zampini   nneu             = 0;
25484edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
25494edc6404Sstefano_zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu);CHKERRQ(ierr);
25504edc6404Sstefano_zampini   }
25513369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
25524edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
25531f4df5f7SStefano Zampini     PetscInt n,i,j;
25541f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
25551f4df5f7SStefano Zampini     PetscInt *iwork;
25561f4df5f7SStefano Zampini 
25571f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
25581f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25591f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
25601f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
256190648384SStefano Zampini     for (i=1;i<n_neigh;i++)
25621f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
25631f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
25641f4df5f7SStefano Zampini     for (i=0;i<n;i++)
25651f4df5f7SStefano Zampini       if (!iwork[i])
25661f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
25671f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
25681f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
25691f4df5f7SStefano Zampini   }
25704f1b2e48SStefano Zampini   if (has_null_pressures) {
25714f1b2e48SStefano Zampini     IS             *subs;
25724edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
25731f4df5f7SStefano Zampini     const PetscInt *idxs;
25741f4df5f7SStefano Zampini     PetscScalar    *array;
25751f4df5f7SStefano Zampini     Vec            *work;
25761f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25774f1b2e48SStefano Zampini 
25784f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
25794f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
25801f4df5f7SStefano 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) */
25814edc6404Sstefano_zampini     if (checkb) {
25821f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
25831f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
25841f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
25851f4df5f7SStefano Zampini       /* work[0] = 1_p */
25861f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
25871f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
25881f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
25891f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
25901f4df5f7SStefano Zampini       /* work[0] = 1_v */
25911f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
25921f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
25931f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
25941f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
25951f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
25961f4df5f7SStefano Zampini     }
25974f1b2e48SStefano Zampini     if (nsubs > 1) {
25984f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
25994f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
26004f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
26014f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
26024f1b2e48SStefano Zampini         PetscInt               nl;
26034f1b2e48SStefano Zampini 
26044f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
26054f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
26064f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
26074f1b2e48SStefano Zampini         if (nl) {
26084f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
26094f1b2e48SStefano Zampini 
26104edc6404Sstefano_zampini           if (checkb) {
26111f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
26121f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
26131f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
26141f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26151f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26161f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26171f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
26181f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
26191f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
26201f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
26211f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
26221f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
26231f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26241f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
26251f4df5f7SStefano Zampini                 break;
26261f4df5f7SStefano Zampini               }
26271f4df5f7SStefano Zampini             }
26281f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
26291f4df5f7SStefano Zampini           }
26306632bad2Sstefano_zampini           if (valid && nneu) {
26316632bad2Sstefano_zampini             const PetscInt *idxs;
26321f4df5f7SStefano Zampini             PetscInt       nzb;
26331f4df5f7SStefano Zampini 
26346632bad2Sstefano_zampini             ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26356632bad2Sstefano_zampini             ierr = ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL);CHKERRQ(ierr);
26366632bad2Sstefano_zampini             ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
26371f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
26381f4df5f7SStefano Zampini           }
26391f4df5f7SStefano Zampini           if (valid && pressures) {
26404f1b2e48SStefano Zampini             IS t_pressure_subs;
26414f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
26424f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
26434f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
26444f1b2e48SStefano Zampini           }
26454f1b2e48SStefano Zampini           if (valid) {
26464f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
26474f1b2e48SStefano Zampini             pcbddc->benign_n++;
26484f1b2e48SStefano Zampini           } else {
26494f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
26504f1b2e48SStefano Zampini           }
26514f1b2e48SStefano Zampini         }
26524f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
26534f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
26544f1b2e48SStefano Zampini       }
26554f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
26564f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
26571f4df5f7SStefano Zampini 
26586632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
26591f4df5f7SStefano Zampini       if (valid && pressures) {
26604f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
26614f1b2e48SStefano Zampini       }
26624edc6404Sstefano_zampini       if (valid && checkb) {
26631f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
26641f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
26651f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
26661f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
26671f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
26681f4df5f7SStefano Zampini             valid = PETSC_FALSE;
26691f4df5f7SStefano Zampini             break;
26701f4df5f7SStefano Zampini           }
26711f4df5f7SStefano Zampini         }
26721f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
26731f4df5f7SStefano Zampini       }
26744f1b2e48SStefano Zampini       if (valid) {
26754f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2676ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
26774f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
26784f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
26794f1b2e48SStefano Zampini       }
26804f1b2e48SStefano Zampini     }
26814edc6404Sstefano_zampini     if (checkb) {
26821f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
26834f1b2e48SStefano Zampini     }
26841f4df5f7SStefano Zampini   }
26851f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
26864f1b2e48SStefano Zampini 
26874f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2688b9b0e38cSStefano Zampini     PetscInt n;
2689b9b0e38cSStefano Zampini 
26904f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
26914f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2692b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2693b9b0e38cSStefano Zampini     if (n) {
26944f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
26954f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
26964f1b2e48SStefano Zampini     }
2697b9b0e38cSStefano Zampini   }
26984f1b2e48SStefano Zampini 
26994f1b2e48SStefano Zampini   /* final check for null pressures */
27004f1b2e48SStefano Zampini   if (zerodiag && pressures) {
27014f1b2e48SStefano Zampini     PetscInt nz,np;
27024f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
27034f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
27044f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
27054f1b2e48SStefano Zampini   }
27064f1b2e48SStefano Zampini 
27074f1b2e48SStefano Zampini   if (recompute_zerodiag) {
27084f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
27094f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
27104f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
27114f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
27124f1b2e48SStefano Zampini     } else {
27134f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
27144f1b2e48SStefano Zampini 
27154f1b2e48SStefano Zampini       nzn = 0;
27164f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27174f1b2e48SStefano Zampini         PetscInt ns;
27184f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27194f1b2e48SStefano Zampini         nzn += ns;
27204f1b2e48SStefano Zampini       }
27214f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
27224f1b2e48SStefano Zampini       nzn = 0;
27234f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27244f1b2e48SStefano Zampini         PetscInt ns,*idxs;
27254f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
27264f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27274f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
27284f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
27294f1b2e48SStefano Zampini         nzn += ns;
27304f1b2e48SStefano Zampini       }
27314f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
27324f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
27334f1b2e48SStefano Zampini     }
27344f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
27354f1b2e48SStefano Zampini   }
27364f1b2e48SStefano Zampini 
2737669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2738a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2739a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2740a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2741a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2742a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2743a198735bSStefano Zampini 
27441f4df5f7SStefano Zampini     if (pressures) {
27451f4df5f7SStefano Zampini       isused = pressures;
27461f4df5f7SStefano Zampini     } else {
27474edc6404Sstefano_zampini       isused = zerodiag_save;
27481f4df5f7SStefano Zampini     }
2749a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2750669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
27511ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
27521ae86dd6SStefano 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");
2753a198735bSStefano Zampini     n_isused = 0;
2754a198735bSStefano Zampini     if (isused) {
2755a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2756a198735bSStefano Zampini     }
2757a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2758a198735bSStefano Zampini     st = st-n_isused;
27591ae86dd6SStefano Zampini     if (n) {
2760a198735bSStefano Zampini       const PetscInt *gidxs;
2761a198735bSStefano Zampini 
27627dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2763a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2764a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2765a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2766a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2767a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
27681ae86dd6SStefano Zampini     } else {
2769a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2770a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2771a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2772a198735bSStefano Zampini     }
2773a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2774a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2775a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2776a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2777a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2778a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2779a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2780a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2781a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2782a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2783a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2784a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2785a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2786a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
27871ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27881ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27891ae86dd6SStefano Zampini   }
27904edc6404Sstefano_zampini   ierr = ISDestroy(&zerodiag_save);CHKERRQ(ierr);
2791b3afcdbeSStefano Zampini 
2792b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
27934f1b2e48SStefano Zampini   if (has_null_pressures) {
27944f1b2e48SStefano Zampini     IS             zerodiagc;
27954f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
27964f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
27974f1b2e48SStefano Zampini 
27984f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2799339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2800339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2801339f8db1SStefano Zampini     /* local change of basis for pressures */
2802339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
280397d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2804339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2805339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2806339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
28074f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
28084f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
28094f1b2e48SStefano Zampini       PetscInt nzs,j;
28104f1b2e48SStefano Zampini 
28114f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
28124f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28134f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
28144f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
28154f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
28164f1b2e48SStefano Zampini     }
2817339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2818339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2819339f8db1SStefano Zampini     /* set identity on velocities */
2820339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2821339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2822339f8db1SStefano Zampini     }
28234f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
28244f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
28259f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
28264f1b2e48SStefano 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);
2827339f8db1SStefano Zampini     /* set change on pressures */
28284f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
28294f1b2e48SStefano Zampini       PetscScalar *array;
28304f1b2e48SStefano Zampini       PetscInt    nzs;
28314f1b2e48SStefano Zampini 
28324f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
28334f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
28344f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2835339f8db1SStefano Zampini         PetscScalar vals[2];
2836339f8db1SStefano Zampini         PetscInt    cols[2];
2837339f8db1SStefano Zampini 
2838339f8db1SStefano Zampini         cols[0] = idxs[i];
28394f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2840339f8db1SStefano Zampini         vals[0] = 1.;
2841b0f5fe93SStefano Zampini         vals[1] = 1.;
28424f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2843339f8db1SStefano Zampini       }
28444f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
28454f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
28464f1b2e48SStefano Zampini       array[nzs-1] = 1.;
28474f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
28484f1b2e48SStefano Zampini       /* store local idxs for p0 */
28494f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
28504f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2851339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
28524f1b2e48SStefano Zampini     }
2853339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2854339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2855a3df083aSStefano Zampini     /* project if needed */
2856a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
28571dd7afcfSStefano Zampini       Mat M;
28581dd7afcfSStefano Zampini 
28591dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2860339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28611dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
28621dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2863a3df083aSStefano Zampini     }
28644f1b2e48SStefano Zampini     /* store global idxs for p0 */
28654f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2866339f8db1SStefano Zampini   }
2867ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28684f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2869b0f5fe93SStefano Zampini 
2870b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2871b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
287227b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
287327b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2874339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2875339f8db1SStefano Zampini   PetscFunctionReturn(0);
2876339f8db1SStefano Zampini }
2877339f8db1SStefano Zampini 
2878015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2879efc2fbd9SStefano Zampini {
2880efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2881de9d7bd0SStefano Zampini   PetscScalar    *array;
2882efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2883efc2fbd9SStefano Zampini 
2884efc2fbd9SStefano Zampini   PetscFunctionBegin;
2885efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2886efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
28874f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2888efc2fbd9SStefano Zampini   }
2889de9d7bd0SStefano Zampini   if (get) {
2890efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
28914f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
28924f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2893efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2894de9d7bd0SStefano Zampini   } else {
2895de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2896de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2897de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2898de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2899efc2fbd9SStefano Zampini   }
2900efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2901efc2fbd9SStefano Zampini }
2902efc2fbd9SStefano Zampini 
2903c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2904c263805aSStefano Zampini {
2905c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2906c263805aSStefano Zampini   PetscErrorCode ierr;
2907c263805aSStefano Zampini 
2908c263805aSStefano Zampini   PetscFunctionBegin;
2909c263805aSStefano Zampini   /* TODO: add error checking
2910c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2911c263805aSStefano Zampini     - cannot push before pop.
29121c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2913c263805aSStefano Zampini   */
29144f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2915efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2916efc2fbd9SStefano Zampini   }
2917c263805aSStefano Zampini   if (pop) {
2918a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29194f1b2e48SStefano Zampini       IS       is_p0;
29204f1b2e48SStefano Zampini       MatReuse reuse;
2921c263805aSStefano Zampini 
2922c263805aSStefano Zampini       /* extract B_0 */
29234f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
29244f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
29254f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
29264f1b2e48SStefano Zampini       }
29274f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
29287dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2929c263805aSStefano Zampini       /* remove rows and cols from local problem */
2930c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
293197d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
29324f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
29334f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2934a3df083aSStefano Zampini     } else {
2935a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2936a3df083aSStefano Zampini       PetscScalar *vals;
2937a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2938a3df083aSStefano Zampini 
2939a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2940a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2941a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
29420b5adadeSStefano Zampini         PetscInt *nnz;
2943a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2944a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2945a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2946331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2947331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2948331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2949331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2950331e053bSStefano Zampini         }
2951331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2952331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2953331e053bSStefano Zampini       }
2954a3df083aSStefano Zampini 
2955a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2956a3df083aSStefano Zampini         PetscScalar *array;
2957a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2958a3df083aSStefano Zampini 
2959a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2960a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2961a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2962a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2963a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2964a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2965a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2966a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2967a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2968a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2969a3df083aSStefano Zampini         cum = 0;
2970a3df083aSStefano Zampini         for (j=0;j<n;j++) {
297122db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2972a3df083aSStefano Zampini             vals[cum] = array[j];
2973a3df083aSStefano Zampini             idxs_ins[cum] = j;
2974a3df083aSStefano Zampini             cum++;
2975a3df083aSStefano Zampini           }
2976a3df083aSStefano Zampini         }
2977a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2978a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2979a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2980a3df083aSStefano Zampini       }
2981a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2982a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2983a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2984a3df083aSStefano Zampini     }
2985c263805aSStefano Zampini   } else { /* push */
2986a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29874f1b2e48SStefano Zampini       PetscInt i;
29884f1b2e48SStefano Zampini 
29894f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
29904f1b2e48SStefano Zampini         PetscScalar *B0_vals;
29914f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
29924f1b2e48SStefano Zampini 
29934f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29944f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29957b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
29964f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
29974f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
29984f1b2e48SStefano Zampini       }
2999c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3000c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3001a3df083aSStefano Zampini     } else {
3002a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
3003a3df083aSStefano Zampini     }
3004c263805aSStefano Zampini   }
3005c263805aSStefano Zampini   PetscFunctionReturn(0);
3006c263805aSStefano Zampini }
3007c263805aSStefano Zampini 
300808122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3009b1b3d7a2SStefano Zampini {
3010b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
301108122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
301208122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
301308122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
301408122e43SStefano Zampini   PetscScalar     *work,lwork;
301508122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
301608122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
301708122e43SStefano Zampini   PetscReal       *eigs,thresh;
30181b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3019f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
302008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
302108122e43SStefano Zampini   PetscReal       *rwork;
302208122e43SStefano Zampini #endif
3023b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
3024b1b3d7a2SStefano Zampini 
3025b1b3d7a2SStefano Zampini   PetscFunctionBegin;
3026b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
3027af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
3028d750e150Sstefano_zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for general matrix pencils (herm %d, posdef %d)\nRerun with -sub_schurs_hermitian 1 -sub_schurs_posdef 1 if the problem is SPD",sub_schurs->is_hermitian,sub_schurs->is_posdef);
302906a4e24aSStefano Zampini 
3030fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3031fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3032fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3033fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
30341575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3035fd14bc51SStefano Zampini   }
3036fd14bc51SStefano Zampini 
3037e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
3038e496cd5dSStefano Zampini     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
3039e496cd5dSStefano Zampini   }
3040e496cd5dSStefano Zampini 
304108122e43SStefano Zampini   /* max size of subsets */
304208122e43SStefano Zampini   mss = 0;
304308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
304408122e43SStefano Zampini     PetscInt subset_size;
3045862806e4SStefano Zampini 
304608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
304708122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
304808122e43SStefano Zampini   }
304908122e43SStefano Zampini 
305008122e43SStefano Zampini   /* min/max and threshold */
305108122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3052f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
305308122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3054f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3055f6f667cfSStefano Zampini   if (nmin) {
3056f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3057f6f667cfSStefano Zampini   }
305808122e43SStefano Zampini 
305908122e43SStefano Zampini   /* allocate lapack workspace */
306008122e43SStefano Zampini   cum = cum2 = 0;
306108122e43SStefano Zampini   maxneigs = 0;
306208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
306308122e43SStefano Zampini     PetscInt n,subset_size;
3064f6f667cfSStefano Zampini 
306508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
306608122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
30679162d606SStefano Zampini     cum += subset_size;
30689162d606SStefano Zampini     cum2 += subset_size*n;
306908122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
307008122e43SStefano Zampini   }
307108122e43SStefano Zampini   if (mss) {
30729ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
307308122e43SStefano Zampini       PetscBLASInt B_itype = 1;
307408122e43SStefano Zampini       PetscBLASInt B_N = mss;
30754c6709b3SStefano Zampini       PetscReal    zero = 0.0;
30764c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
307708122e43SStefano Zampini 
307808122e43SStefano Zampini       B_lwork = -1;
307908122e43SStefano Zampini       S = NULL;
308008122e43SStefano Zampini       St = NULL;
3081a58a30b4SStefano Zampini       eigs = NULL;
3082a58a30b4SStefano Zampini       eigv = NULL;
3083a58a30b4SStefano Zampini       B_iwork = NULL;
3084a58a30b4SStefano Zampini       B_ifail = NULL;
3085d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3086d1710679SStefano Zampini       rwork = NULL;
3087d1710679SStefano Zampini #endif
30888bec7fa6SStefano Zampini       thresh = 1.0;
308908122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
309008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
309108122e43SStefano 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));
309208122e43SStefano Zampini #else
309308122e43SStefano 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));
309408122e43SStefano Zampini #endif
309508122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
309608122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
309708122e43SStefano Zampini     } else {
309808122e43SStefano Zampini         /* TODO */
309908122e43SStefano Zampini     }
310008122e43SStefano Zampini   } else {
310108122e43SStefano Zampini     lwork = 0;
310208122e43SStefano Zampini   }
310308122e43SStefano Zampini 
310408122e43SStefano Zampini   nv = 0;
3105d62866d3SStefano 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) */
3106d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
310708122e43SStefano Zampini   }
31084c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
3109f6f667cfSStefano Zampini   if (allocated_S_St) {
3110f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
3111f6f667cfSStefano Zampini   }
3112f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
311308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
311408122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
311508122e43SStefano Zampini #endif
31169162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
31179162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
31189162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
311908122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
31209162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
312108122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
312208122e43SStefano Zampini 
312308122e43SStefano Zampini   maxneigs = 0;
312472b8c272SStefano Zampini   cum = cumarray = 0;
31259162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
31269162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3127d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
312808122e43SStefano Zampini     const PetscInt *idxs;
312908122e43SStefano Zampini 
3130d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
313108122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
313208122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
313308122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
313408122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
31359162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
31369162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
313708122e43SStefano Zampini     }
3138d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
313908122e43SStefano Zampini   }
314008122e43SStefano Zampini 
314108122e43SStefano Zampini   if (mss) { /* multilevel */
314208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
314308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
314408122e43SStefano Zampini   }
314508122e43SStefano Zampini 
3146ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
314708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
314808122e43SStefano Zampini     const PetscInt *idxs;
31499d54b7f4SStefano Zampini     PetscReal      upper,lower;
3150862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
315108122e43SStefano Zampini     PetscBLASInt   B_N;
3152aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
315308122e43SStefano Zampini 
31549d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
31559d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
31569d54b7f4SStefano Zampini       lower = thresh;
31579d54b7f4SStefano Zampini     } else {
31589d54b7f4SStefano Zampini       upper = 1./thresh;
31599d54b7f4SStefano Zampini       lower = 0.;
31609d54b7f4SStefano Zampini     }
3161862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
3162ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
3163f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
3164f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
31659ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
3166aff50787SStefano Zampini         PetscInt j,k;
3167aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
3168aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3169aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
317008122e43SStefano Zampini         }
317108122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3172aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3173aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3174aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3175aff50787SStefano Zampini           }
317608122e43SStefano Zampini         }
317708122e43SStefano Zampini       } else {
317808122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
317908122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
318008122e43SStefano Zampini       }
31818bec7fa6SStefano Zampini     } else {
3182f6f667cfSStefano Zampini       S = Sarray + cumarray;
3183f6f667cfSStefano Zampini       St = Starray + cumarray;
31848bec7fa6SStefano Zampini     }
3185aff50787SStefano Zampini     /* see if we can save some work */
3186b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
3187aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
3188aff50787SStefano Zampini     }
3189aff50787SStefano Zampini 
3190b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3191aff50787SStefano Zampini       B_neigs = 0;
3192aff50787SStefano Zampini     } else {
31939ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
319408122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3195f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
31964c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
31979552c7c7SStefano Zampini         PetscInt     nmin_s;
3198b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
319908122e43SStefano Zampini 
3200fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3201eee23b56SStefano Zampini           PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d size %d count %d fid %d.\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]+1,pcbddc->mat_graph->which_dof[idxs[0]]);
3202fd14bc51SStefano Zampini         }
3203d16cbb6bSStefano Zampini 
3204b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
3205b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
3206b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
3207b7ab4a40SStefano Zampini         }
3208b7ab4a40SStefano Zampini 
320908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3210b7ab4a40SStefano Zampini         if (compute_range) {
3211d16cbb6bSStefano Zampini 
3212d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
321308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32149d54b7f4SStefano 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));
321508122e43SStefano Zampini #else
32169d54b7f4SStefano 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));
321708122e43SStefano Zampini #endif
3218b7ab4a40SStefano Zampini         } else if (!same_data) {
3219d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3220d16cbb6bSStefano Zampini           B_IL = 1;
3221d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
32229d54b7f4SStefano 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));
3223d16cbb6bSStefano Zampini #else
32249d54b7f4SStefano 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));
3225d16cbb6bSStefano Zampini #endif
3226b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3227b7ab4a40SStefano Zampini           PetscInt k;
3228b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
3229b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
3230b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
3231b7ab4a40SStefano Zampini           nmin = nmax;
3232b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
3233b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3234b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3235b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3236b7ab4a40SStefano Zampini           }
3237d16cbb6bSStefano Zampini         }
323808122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
323908122e43SStefano Zampini         if (B_ierr) {
32406c4ed002SBarry 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);
32416c4ed002SBarry 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);
32426c4ed002SBarry 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);
324308122e43SStefano Zampini         }
324408122e43SStefano Zampini 
324508122e43SStefano Zampini         if (B_neigs > nmax) {
3246fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3247fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
3248fd14bc51SStefano Zampini           }
32499d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
325008122e43SStefano Zampini           B_neigs = nmax;
325108122e43SStefano Zampini         }
325208122e43SStefano Zampini 
32539552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
32549552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
325508122e43SStefano Zampini           PetscBLASInt B_neigs2;
325608122e43SStefano Zampini 
32579d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3258f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
32599d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
32609d54b7f4SStefano Zampini           } else {
32619d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
32629d54b7f4SStefano Zampini             B_IU = nmin_s;
32639d54b7f4SStefano Zampini           }
3264fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
3265fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %d. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);
3266fd14bc51SStefano Zampini           }
32679ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
32681ae86dd6SStefano Zampini             PetscInt j,k;
326908122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
32701ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
32711ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
32721ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
327308122e43SStefano Zampini               }
327408122e43SStefano Zampini             }
327508122e43SStefano Zampini           } else {
327608122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
327708122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
327808122e43SStefano Zampini           }
327908122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
328008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32819d54b7f4SStefano 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));
328208122e43SStefano Zampini #else
32839d54b7f4SStefano 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));
328408122e43SStefano Zampini #endif
328508122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
328608122e43SStefano Zampini           B_neigs += B_neigs2;
328708122e43SStefano Zampini         }
328808122e43SStefano Zampini         if (B_ierr) {
32896c4ed002SBarry 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);
32906c4ed002SBarry 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);
32916c4ed002SBarry 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);
329208122e43SStefano Zampini         }
3293fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3294ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
329508122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
329608122e43SStefano Zampini             if (eigs[j] == 0.0) {
3297ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
329808122e43SStefano Zampini             } else {
32999d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3300ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
33019d54b7f4SStefano Zampini               } else {
33029d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
33039d54b7f4SStefano Zampini               }
3304fd14bc51SStefano Zampini             }
330508122e43SStefano Zampini           }
330608122e43SStefano Zampini         }
330708122e43SStefano Zampini       } else {
330808122e43SStefano Zampini           /* TODO */
330908122e43SStefano Zampini       }
3310aff50787SStefano Zampini     }
33116c3e6151SStefano Zampini     /* change the basis back to the original one */
33126c3e6151SStefano Zampini     if (sub_schurs->change) {
331372b8c272SStefano Zampini       Mat change,phi,phit;
33146c3e6151SStefano Zampini 
331503dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
33166c3e6151SStefano Zampini         PetscInt ii;
33176c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
33186c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
33196c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3320684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3321684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3322684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3323684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3324684229deSStefano Zampini #else
33256c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3326684229deSStefano Zampini #endif
33276c3e6151SStefano Zampini           }
33286c3e6151SStefano Zampini         }
33296c3e6151SStefano Zampini       }
333072b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
33316c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
333272b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
33336c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
33346c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
33356c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
33366c3e6151SStefano Zampini     }
33378bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
33388bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
33399162d606SStefano Zampini     if (B_neigs) {
33409162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
3341fd14bc51SStefano Zampini 
3342fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
33439552c7c7SStefano Zampini         PetscInt ii;
33449552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3345ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
33469552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3347ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3348ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3349ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3350ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3351ac47001eSStefano Zampini #else
3352ac47001eSStefano 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);
3353ac47001eSStefano Zampini #endif
33549552c7c7SStefano Zampini           }
33559552c7c7SStefano Zampini         }
3356fd14bc51SStefano Zampini       }
33579162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
33589162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
33599162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
33609162d606SStefano Zampini       cum++;
336108122e43SStefano Zampini     }
336208122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
336308122e43SStefano Zampini     /* shift for next computation */
336408122e43SStefano Zampini     cumarray += subset_size*subset_size;
336508122e43SStefano Zampini   }
3366fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3367fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3368fd14bc51SStefano Zampini   }
336908122e43SStefano Zampini 
337008122e43SStefano Zampini   if (mss) {
337108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
337208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3373f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3374f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3375f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
337608122e43SStefano Zampini   }
3377f6f667cfSStefano Zampini   if (allocated_S_St) {
3378f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3379f6f667cfSStefano Zampini   }
3380f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
338108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
338208122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
338308122e43SStefano Zampini #endif
338408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
33851b968477SStefano Zampini     PetscInt maxneigs_r;
3386b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
33879b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
338808122e43SStefano Zampini   }
338908122e43SStefano Zampini   PetscFunctionReturn(0);
339008122e43SStefano Zampini }
3391b1b3d7a2SStefano Zampini 
3392c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3393c8587f34SStefano Zampini {
33948629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3395c8587f34SStefano Zampini   PetscErrorCode ierr;
3396c8587f34SStefano Zampini 
3397c8587f34SStefano Zampini   PetscFunctionBegin;
3398f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
33995e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3400c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3401c8587f34SStefano Zampini 
3402684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
34030fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3404684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3405c8587f34SStefano Zampini 
34068629588bSStefano Zampini   /*
34078629588bSStefano Zampini      Setup local correction and local part of coarse basis.
34088629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
34098629588bSStefano Zampini   */
341047f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
34118629588bSStefano Zampini 
34128629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
34138629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
34148629588bSStefano Zampini 
34158629588bSStefano Zampini   /* free */
34168629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3417c8587f34SStefano Zampini   PetscFunctionReturn(0);
3418c8587f34SStefano Zampini }
3419c8587f34SStefano Zampini 
3420674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3421674ae819SStefano Zampini {
3422674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3423674ae819SStefano Zampini   PetscErrorCode ierr;
3424674ae819SStefano Zampini 
3425674ae819SStefano Zampini   PetscFunctionBegin;
3426674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
342730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3428674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3429785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3430674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3431f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3432f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3433785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
343463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
343563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3436674ae819SStefano Zampini   PetscFunctionReturn(0);
3437674ae819SStefano Zampini }
3438674ae819SStefano Zampini 
3439674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3440674ae819SStefano Zampini {
3441674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
34424f1b2e48SStefano Zampini   PetscInt       i;
3443674ae819SStefano Zampini   PetscErrorCode ierr;
3444674ae819SStefano Zampini 
3445674ae819SStefano Zampini   PetscFunctionBegin;
34461e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
34471e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3448a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3449b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3450674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
345116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
34521dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3453674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3454669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3455fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
34569326c5c6Sstefano_zampini   ierr = PCBDDCGraphDestroy(&pcbddc->mat_graph);CHKERRQ(ierr);
34574f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
34584f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
34594f1b2e48SStefano Zampini   }
3460e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
34614f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3462e68a0315Sstefano_zampini   ierr = PCBDDCSubSchursDestroy(&pcbddc->sub_schurs);CHKERRQ(ierr);
3463c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
34648af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3465674ae819SStefano Zampini   PetscFunctionReturn(0);
3466674ae819SStefano Zampini }
3467674ae819SStefano Zampini 
3468674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3469674ae819SStefano Zampini {
3470674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3471674ae819SStefano Zampini   PetscErrorCode ierr;
3472674ae819SStefano Zampini 
3473674ae819SStefano Zampini   PetscFunctionBegin;
3474674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
347558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3476ca92afb2SStefano Zampini     PetscScalar *array;
347706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
347806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
347958da7f69SStefano Zampini   }
3480674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3481674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
348215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
348315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3484674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3485674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3486674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
348706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3488674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3489674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
34908ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3491674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3492674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3493674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
34949326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_D);CHKERRQ(ierr);
34959326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
34969326c5c6Sstefano_zampini   ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3497f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3498727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
34990e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3500f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
350170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
350281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
35030369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
35041dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
35054f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
35068b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3507ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3508ca92afb2SStefano Zampini     PetscInt i;
3509ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3510ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3511ca92afb2SStefano Zampini     }
3512ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3513ca92afb2SStefano Zampini   }
35144f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3515674ae819SStefano Zampini   PetscFunctionReturn(0);
3516674ae819SStefano Zampini }
3517674ae819SStefano Zampini 
3518f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
35196bfb1811SStefano Zampini {
35206bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
35216bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
35226bfb1811SStefano Zampini   VecType        impVecType;
35234f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
35246bfb1811SStefano Zampini   PetscErrorCode ierr;
35256bfb1811SStefano Zampini 
35266bfb1811SStefano Zampini   PetscFunctionBegin;
35274f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3528b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
35296bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3530e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3531e7b262bdSStefano Zampini   /* R nodes */
3532e7b262bdSStefano Zampini   old_size = -1;
3533e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3534e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3535e7b262bdSStefano Zampini   }
3536e7b262bdSStefano Zampini   if (n_R != old_size) {
3537e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3538e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
35396bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
35406bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
35416bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
35426bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3543e7b262bdSStefano Zampini   }
3544e7b262bdSStefano Zampini   /* local primal dofs */
3545e7b262bdSStefano Zampini   old_size = -1;
3546e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3547e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3548e7b262bdSStefano Zampini   }
3549e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3550e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
355183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3552e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
35536bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3554e7b262bdSStefano Zampini   }
3555e7b262bdSStefano Zampini   /* local explicit constraints */
3556e7b262bdSStefano Zampini   old_size = -1;
3557e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3558e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3559e7b262bdSStefano Zampini   }
3560e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3561e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
356283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
356383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
356483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
356583b7ccabSStefano Zampini   }
35666bfb1811SStefano Zampini   PetscFunctionReturn(0);
35676bfb1811SStefano Zampini }
35686bfb1811SStefano Zampini 
356947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
357088ebb749SStefano Zampini {
357125084f0cSStefano Zampini   PetscErrorCode  ierr;
357225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
357388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
357488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3575d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
357625084f0cSStefano Zampini   /* submatrices of local problem */
357780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
357806656605SStefano Zampini   /* submatrices of local coarse problem */
357906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
358025084f0cSStefano Zampini   /* working matrices */
358106656605SStefano Zampini   Mat             C_CR;
358225084f0cSStefano Zampini   /* additional working stuff */
358306656605SStefano Zampini   PC              pc_R;
3584c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
35855cbda25cSStefano Zampini   Vec             dummy_vec;
3586c58f9fdbSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction,sparserhs;
358725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
358806656605SStefano Zampini   PetscScalar     *work;
358906656605SStefano Zampini   PetscInt        *idx_V_B;
3590ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
359106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3592ffd830a3SStefano Zampini 
359325084f0cSStefano Zampini   /* some shortcuts to scalars */
359406656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
359588ebb749SStefano Zampini 
359688ebb749SStefano Zampini   PetscFunctionBegin;
35979a962809SStefano 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");
3598ffd830a3SStefano Zampini 
3599ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3600b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
36014f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3602b371cd4fSStefano Zampini   n_B = pcis->n_B;
3603b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
360488ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
360588ebb749SStefano Zampini 
360688ebb749SStefano Zampini   /* vertices in boundary numbering */
3607785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
36080e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
36096c4ed002SBarry Smith   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",n_vertices,i);
361088ebb749SStefano Zampini 
361106656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3612019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
361306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
361406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
361506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
361606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
361706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
361806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
361906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
362006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
362106656605SStefano Zampini 
362206656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
362306656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
362406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
362506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
362606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3627ffd830a3SStefano Zampini   lda_rhs = n_R;
3628a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
362906656605SStefano Zampini   if (isLU || isILU || isCHOL) {
363006656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3631b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3632df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3633d62866d3SStefano Zampini     MatFactorType      type;
3634d62866d3SStefano Zampini 
3635df4d28bfSStefano Zampini     F = reuse_solver->F;
36366816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3637d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3638ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
363922db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
364006656605SStefano Zampini   } else {
364106656605SStefano Zampini     F = NULL;
364206656605SStefano Zampini   }
364306656605SStefano Zampini 
3644c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3645c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3646c58f9fdbSStefano Zampini   if (F) {
3647ea799195SBarry Smith     MatSolverType solver;
3648c58f9fdbSStefano Zampini 
36493ca39a21SBarry Smith     ierr = MatFactorGetSolverType(F,&solver);CHKERRQ(ierr);
3650c58f9fdbSStefano Zampini     ierr = PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs);CHKERRQ(ierr);
3651c58f9fdbSStefano Zampini   }
3652c58f9fdbSStefano Zampini 
3653ffd830a3SStefano Zampini   /* allocate workspace */
3654ffd830a3SStefano Zampini   n = 0;
3655ffd830a3SStefano Zampini   if (n_constraints) {
3656ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3657ffd830a3SStefano Zampini   }
3658ffd830a3SStefano Zampini   if (n_vertices) {
3659ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3660ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3661ffd830a3SStefano Zampini   }
36622a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
36632a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
36642a3a6641Sstefano_zampini   }
3665ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3666ffd830a3SStefano Zampini 
36675cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
36685cbda25cSStefano Zampini   dummy_vec = NULL;
36695cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
36705cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
36715cbda25cSStefano Zampini   }
36725cbda25cSStefano Zampini 
367388ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
367488ebb749SStefano Zampini   if (n_constraints) {
3675*837cedc9SStefano Zampini     Mat         M3,C_B;
367606656605SStefano Zampini     IS          is_aux;
367780677318SStefano Zampini     PetscScalar *array,*array2;
367806656605SStefano Zampini 
3679f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
368080677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
368188ebb749SStefano Zampini 
368225084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
368325084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
36847dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
36857dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
368688ebb749SStefano Zampini 
368780677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
368880677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3689c58f9fdbSStefano Zampini     if (!sparserhs) {
3690ffd830a3SStefano Zampini       ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
369188ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
369206656605SStefano Zampini         const PetscScalar *row_cmat_values;
369306656605SStefano Zampini         const PetscInt    *row_cmat_indices;
369406656605SStefano Zampini         PetscInt          size_of_constraint,j;
369588ebb749SStefano Zampini 
369606656605SStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
369706656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
3698ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
369906656605SStefano Zampini         }
370006656605SStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
370106656605SStefano Zampini       }
3702c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs);CHKERRQ(ierr);
3703c58f9fdbSStefano Zampini     } else {
3704c58f9fdbSStefano Zampini       Mat tC_CR;
3705c58f9fdbSStefano Zampini 
3706c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3707c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
3708c58f9fdbSStefano Zampini         PetscScalar *aa;
3709c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
3710c58f9fdbSStefano Zampini         PetscBool   done;
3711c58f9fdbSStefano Zampini 
3712c58f9fdbSStefano Zampini         ierr = MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
371313903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
3714c58f9fdbSStefano Zampini         ierr = MatSeqAIJGetArray(C_CR,&aa);CHKERRQ(ierr);
3715c58f9fdbSStefano Zampini         ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR);CHKERRQ(ierr);
3716c58f9fdbSStefano Zampini         ierr = MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
371713903a91SSatish Balay         if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
3718c58f9fdbSStefano Zampini       } else {
3719c58f9fdbSStefano Zampini         ierr  = PetscObjectReference((PetscObject)C_CR);CHKERRQ(ierr);
3720c58f9fdbSStefano Zampini         tC_CR = C_CR;
3721c58f9fdbSStefano Zampini       }
3722c58f9fdbSStefano Zampini       ierr = MatCreateTranspose(tC_CR,&Brhs);CHKERRQ(ierr);
3723c58f9fdbSStefano Zampini       ierr = MatDestroy(&tC_CR);CHKERRQ(ierr);
3724c58f9fdbSStefano Zampini     }
3725ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
372606656605SStefano Zampini     if (F) {
3727a3df083aSStefano Zampini       if (need_benign_correction) {
3728df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3729a3df083aSStefano Zampini 
373072b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
373172b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3732a3df083aSStefano Zampini       }
3733c58f9fdbSStefano Zampini       ierr = MatMatSolve(F,Brhs,local_auxmat2_R);CHKERRQ(ierr);
3734a3df083aSStefano Zampini       if (need_benign_correction) {
3735a3df083aSStefano Zampini         PetscScalar        *marr;
3736df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3737a3df083aSStefano Zampini 
3738a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
37395cbda25cSStefano Zampini         if (lda_rhs != n_R) {
37405cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
37415cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
37425cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
37435cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
37445cbda25cSStefano Zampini           }
37455cbda25cSStefano Zampini         } else {
3746a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3747a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
37485cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3749a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3750a3df083aSStefano Zampini           }
37515cbda25cSStefano Zampini         }
3752a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3753a3df083aSStefano Zampini       }
375406656605SStefano Zampini     } else {
375580677318SStefano Zampini       PetscScalar *marr;
375680677318SStefano Zampini 
375780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
375806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3759ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3760ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
376106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
376206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
376306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
376406656605SStefano Zampini       }
376580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
376606656605SStefano Zampini     }
3767c58f9fdbSStefano Zampini     if (sparserhs) {
3768c58f9fdbSStefano Zampini       ierr = MatScale(C_CR,-1.0);CHKERRQ(ierr);
3769c58f9fdbSStefano Zampini     }
3770c58f9fdbSStefano Zampini     ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
377180677318SStefano Zampini     if (!pcbddc->switch_static) {
377280677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
377380677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
377480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
377580677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3776ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
377780677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
377880677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
377980677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
378080677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
378180677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
378280677318SStefano Zampini       }
378380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
378480677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
378572b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
378680677318SStefano Zampini     } else {
3787ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3788ffd830a3SStefano Zampini         IS dummy;
3789ffd830a3SStefano Zampini 
3790ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
37917dae84e0SHong Zhang         ierr = MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3792ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3793ffd830a3SStefano Zampini       } else {
379480677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
379580677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3796ffd830a3SStefano Zampini       }
379725084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
379880677318SStefano Zampini     }
379980677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
380080677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
380180677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
380280677318SStefano Zampini     if (isCHOL) {
380380677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
380480677318SStefano Zampini     } else {
380525084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
380680677318SStefano Zampini     }
3807*837cedc9SStefano Zampini     ierr = MatSeqDenseInvertFactors_Private(M3);CHKERRQ(ierr);
380880677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
3809*837cedc9SStefano Zampini     ierr = MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
381072b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
3811*837cedc9SStefano Zampini     ierr = MatCopy(M3,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
3812*837cedc9SStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
3813f4ddd8eeSStefano Zampini   }
3814fc227af8SStefano Zampini 
3815fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
381688ebb749SStefano Zampini   if (n_vertices) {
381706656605SStefano Zampini     IS        is_aux;
3818c58f9fdbSStefano Zampini     PetscBool isseqaij;
38193a50541eSStefano Zampini 
3820b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
38216816873aSStefano Zampini       IS tis;
38226816873aSStefano Zampini 
38236816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
38246816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
38256816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
38266816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
38276816873aSStefano Zampini     } else {
38283a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
38296816873aSStefano Zampini     }
38307dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
38317dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3832c58f9fdbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3833c58f9fdbSStefano Zampini     if (!isseqaij) { /* MatMatMult(A_VR,A_RRmA_RV) below will raise an error */
3834c58f9fdbSStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3835c58f9fdbSStefano Zampini     }
38367dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
383725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
383888ebb749SStefano Zampini   }
383988ebb749SStefano Zampini 
384088ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3841f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
384206656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
384306656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
384406656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
384506656605SStefano Zampini     }
3846f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
384706656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
384806656605SStefano Zampini       PetscScalar *marray;
384906656605SStefano Zampini 
385006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
385106656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3852f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3853f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3854f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3855f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3856f4ddd8eeSStefano Zampini     }
3857f4ddd8eeSStefano Zampini   }
385806656605SStefano Zampini 
3859f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
3860a6e023c1Sstefano_zampini     PetscScalar *marr;
386188ebb749SStefano Zampini 
3862a6e023c1Sstefano_zampini     /* memory size */
386306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
3864a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
3865a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
3866a6e023c1Sstefano_zampini     ierr  = PetscCalloc1(n,&marr);CHKERRQ(ierr);
3867a6e023c1Sstefano_zampini     ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3868a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
38698eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3870a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3871a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
387288ebb749SStefano Zampini     }
38733301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
3874a6e023c1Sstefano_zampini       ierr  = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3875a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
38768eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3877a6e023c1Sstefano_zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
387888ebb749SStefano Zampini       }
387988ebb749SStefano Zampini     } else {
3880c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3881c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
38821b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3883c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3884c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3885c0553b1fSStefano Zampini       }
388688ebb749SStefano Zampini     }
388706656605SStefano Zampini   }
3888019a44ceSStefano Zampini 
388906656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
38904f1b2e48SStefano Zampini   p0_lidx_I = NULL;
38914f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3892d12edf2fSStefano Zampini     const PetscInt *idxs;
3893d12edf2fSStefano Zampini 
3894d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
38954f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
38964f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
38974f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
38984f1b2e48SStefano Zampini     }
3899d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3900d12edf2fSStefano Zampini   }
3901d16cbb6bSStefano Zampini 
390206656605SStefano Zampini   /* vertices */
390306656605SStefano Zampini   if (n_vertices) {
3904c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
390516f15bc4SStefano Zampini 
3906af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
390704708bb6SStefano Zampini 
390816f15bc4SStefano Zampini     if (n_R) {
390914393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
391006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
391116f15bc4SStefano Zampini       PetscScalar  *x,*y;
391206656605SStefano Zampini 
391321eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
391414393ed6SStefano Zampini       if (need_benign_correction) {
391514393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
391614393ed6SStefano Zampini         IS                     is_p0;
391714393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
391814393ed6SStefano Zampini 
391914393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
392014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
392114393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3922af25d912SStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
392314393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
392414393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
39257dae84e0SHong Zhang         ierr = MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
392614393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
392714393ed6SStefano Zampini       }
392814393ed6SStefano Zampini 
3929c58f9fdbSStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3930c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
3931ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
3932af25d912SStefano Zampini           ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3933ffd830a3SStefano Zampini         } else {
3934ca92afb2SStefano Zampini           PetscScalar    *av,*array;
3935ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
3936ca92afb2SStefano Zampini           PetscInt       n;
3937ca92afb2SStefano Zampini           PetscBool      flg_row;
3938ffd830a3SStefano Zampini 
3939ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
3940ca92afb2SStefano Zampini           ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
39419d54b7f4SStefano Zampini           ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3942ca92afb2SStefano Zampini           ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3943ca92afb2SStefano Zampini           ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3944ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
3945ca92afb2SStefano Zampini             PetscInt j;
3946ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3947ffd830a3SStefano Zampini           }
3948ca92afb2SStefano Zampini           ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3949ca92afb2SStefano Zampini           ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3950ca92afb2SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3951ffd830a3SStefano Zampini         }
3952a3df083aSStefano Zampini         if (need_benign_correction) {
3953df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3954a3df083aSStefano Zampini           PetscScalar        *marr;
3955a3df083aSStefano Zampini 
3956a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
395714393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
395814393ed6SStefano Zampini 
395914393ed6SStefano Zampini                  | 0 0  0 | (V)
396014393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
396114393ed6SStefano Zampini                  | 0 0 -1 | (p0)
396214393ed6SStefano Zampini 
396314393ed6SStefano Zampini           */
3964df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
396514393ed6SStefano Zampini             const PetscScalar *vals;
396614393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
396714393ed6SStefano Zampini             PetscInt          n,j,nz;
396814393ed6SStefano Zampini 
3969df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3970df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
397114393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
397214393ed6SStefano Zampini             for (j=0;j<n;j++) {
397314393ed6SStefano Zampini               PetscScalar val = vals[j];
397414393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
397514393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
397614393ed6SStefano Zampini             }
397714393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3978df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
397914393ed6SStefano Zampini           }
398072b8c272SStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
398172b8c272SStefano Zampini         }
3982c58f9fdbSStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RV);CHKERRQ(ierr);
3983c58f9fdbSStefano Zampini         Brhs = A_RV;
3984c58f9fdbSStefano Zampini       } else {
3985c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
3986c58f9fdbSStefano Zampini 
3987c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
3988c58f9fdbSStefano Zampini           ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT);CHKERRQ(ierr);
3989c58f9fdbSStefano Zampini         } else {
3990c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
3991c58f9fdbSStefano Zampini           ierr  = MatScale(A_VR,-1.0);CHKERRQ(ierr);
3992c58f9fdbSStefano Zampini           ierr  = PetscObjectReference((PetscObject)A_VR);CHKERRQ(ierr);
3993c58f9fdbSStefano Zampini           A_RVT = A_VR;
3994c58f9fdbSStefano Zampini         }
3995c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
3996c58f9fdbSStefano Zampini           PetscScalar *aa;
3997c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
3998c58f9fdbSStefano Zampini           PetscBool   done;
3999c58f9fdbSStefano Zampini 
4000c58f9fdbSStefano Zampini           ierr = MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
400113903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
4002c58f9fdbSStefano Zampini           ierr = MatSeqAIJGetArray(A_RVT,&aa);CHKERRQ(ierr);
4003c58f9fdbSStefano Zampini           ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT);CHKERRQ(ierr);
4004c58f9fdbSStefano Zampini           ierr = MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr);
400513903a91SSatish Balay           if (!done) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4006c58f9fdbSStefano Zampini         } else {
4007c58f9fdbSStefano Zampini           ierr   = PetscObjectReference((PetscObject)A_RVT);CHKERRQ(ierr);
4008c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4009c58f9fdbSStefano Zampini         }
4010c58f9fdbSStefano Zampini         ierr = MatCreateTranspose(tA_RVT,&Brhs);CHKERRQ(ierr);
4011c58f9fdbSStefano Zampini         ierr = MatDestroy(&tA_RVT);CHKERRQ(ierr);
4012c58f9fdbSStefano Zampini         ierr = MatDestroy(&A_RVT);CHKERRQ(ierr);
4013c58f9fdbSStefano Zampini       }
401472b8c272SStefano Zampini       if (F) {
401514393ed6SStefano Zampini         /* need to correct the rhs */
401672b8c272SStefano Zampini         if (need_benign_correction) {
401772b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
401872b8c272SStefano Zampini           PetscScalar        *marr;
401972b8c272SStefano Zampini 
4020c58f9fdbSStefano Zampini           ierr = MatDenseGetArray(Brhs,&marr);CHKERRQ(ierr);
40215cbda25cSStefano Zampini           if (lda_rhs != n_R) {
40225cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
40235cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40245cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
40255cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40265cbda25cSStefano Zampini             }
40275cbda25cSStefano Zampini           } else {
4028a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4029a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40305cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
4031a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4032a3df083aSStefano Zampini             }
40335cbda25cSStefano Zampini           }
4034c58f9fdbSStefano Zampini           ierr = MatDenseRestoreArray(Brhs,&marr);CHKERRQ(ierr);
4035a3df083aSStefano Zampini         }
4036c58f9fdbSStefano Zampini         ierr = MatMatSolve(F,Brhs,A_RRmA_RV);CHKERRQ(ierr);
4037c58f9fdbSStefano Zampini         if (restoreavr) {
4038c58f9fdbSStefano Zampini           ierr = MatScale(A_VR,-1.0);CHKERRQ(ierr);
4039c58f9fdbSStefano Zampini         }
404014393ed6SStefano Zampini         /* need to correct the solution */
4041a3df083aSStefano Zampini         if (need_benign_correction) {
4042df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4043a3df083aSStefano Zampini           PetscScalar        *marr;
4044a3df083aSStefano Zampini 
4045a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
40465cbda25cSStefano Zampini           if (lda_rhs != n_R) {
40475cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
40485cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
40495cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
40505cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
40515cbda25cSStefano Zampini             }
40525cbda25cSStefano Zampini           } else {
4053a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
4054a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
40555cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
4056a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4057a3df083aSStefano Zampini             }
40585cbda25cSStefano Zampini           }
4059a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
4060a3df083aSStefano Zampini         }
406106656605SStefano Zampini       } else {
4062c58f9fdbSStefano Zampini         ierr = MatDenseGetArray(Brhs,&y);CHKERRQ(ierr);
406306656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
4064ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
4065ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
406606656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
406706656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
406806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
406906656605SStefano Zampini         }
4070c58f9fdbSStefano Zampini         ierr = MatDenseRestoreArray(Brhs,&y);CHKERRQ(ierr);
407106656605SStefano Zampini       }
407280677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
4073c58f9fdbSStefano Zampini       ierr = MatDestroy(&Brhs);CHKERRQ(ierr);
4074ffd830a3SStefano Zampini       /* S_VV and S_CV */
407506656605SStefano Zampini       if (n_constraints) {
407606656605SStefano Zampini         Mat B;
407780677318SStefano Zampini 
4078ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
407980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
4080ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
4081ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
408280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
408380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
408480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
408580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
408680677318SStefano Zampini         }
4087ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
408880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
408980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
4090ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
409180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
409206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
4093ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
4094ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
409506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
409606656605SStefano Zampini       }
4097ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4098ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
4099ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
4100ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
4101ffd830a3SStefano Zampini       }
410206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
410314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
410414393ed6SStefano Zampini       if (need_benign_correction) {
4105df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
410614393ed6SStefano Zampini         PetscScalar      *marr,*sums;
410714393ed6SStefano Zampini 
410814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
4109f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
4110df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
411114393ed6SStefano Zampini           const PetscScalar *vals;
411214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
411314393ed6SStefano Zampini           PetscInt          n,j,nz;
411414393ed6SStefano Zampini 
4115df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
4116df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
411714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
411814393ed6SStefano Zampini             PetscInt k;
411914393ed6SStefano Zampini             sums[j] = 0.;
412014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
412114393ed6SStefano Zampini           }
412214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
412314393ed6SStefano Zampini           for (j=0;j<n;j++) {
412414393ed6SStefano Zampini             PetscScalar val = vals[j];
412514393ed6SStefano Zampini             PetscInt k;
412614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
412714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
412814393ed6SStefano Zampini             }
412914393ed6SStefano Zampini           }
413014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
4131df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
413214393ed6SStefano Zampini         }
413314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
4134f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
413514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
413614393ed6SStefano Zampini       }
413780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
413806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
413906656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
414006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
414106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
414206656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
414306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
414406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4145d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
4146019a44ceSStefano Zampini     } else {
4147d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
4148d16cbb6bSStefano Zampini     }
414921eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
4150d16cbb6bSStefano Zampini 
415106656605SStefano Zampini     /* coarse basis functions */
415206656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
415316f15bc4SStefano Zampini       PetscScalar *y;
415416f15bc4SStefano Zampini 
4155ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
415606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
415706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
415806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
415906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
416006656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
416106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
416206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
416306656605SStefano Zampini 
416406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41654f1b2e48SStefano Zampini         PetscInt j;
41664f1b2e48SStefano Zampini 
416706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
416806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
416906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
417006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
417106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
41724f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
417306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
417406656605SStefano Zampini       }
417506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
417606656605SStefano Zampini     }
417704708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
417804708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
417906656605SStefano Zampini   }
41805cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
418106656605SStefano Zampini 
418206656605SStefano Zampini   if (n_constraints) {
418306656605SStefano Zampini     Mat B;
418406656605SStefano Zampini 
4185ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
418606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
418780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
418806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
418906656605SStefano Zampini     if (n_vertices) {
419003dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
419180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
419280677318SStefano Zampini       } else {
419380677318SStefano Zampini         Mat S_VCt;
419480677318SStefano Zampini 
4195ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
4196ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
419772b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
4198ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
4199ffd830a3SStefano Zampini         }
420080677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
420180677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
420280677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
420380677318SStefano Zampini       }
420406656605SStefano Zampini     }
420506656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
420606656605SStefano Zampini     /* coarse basis functions */
420706656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
420806656605SStefano Zampini       PetscScalar *y;
420906656605SStefano Zampini 
4210ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
421106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
421206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
421306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
421406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
421506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
421606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
421706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
42184f1b2e48SStefano Zampini         PetscInt j;
42194f1b2e48SStefano Zampini 
422006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
422106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
422206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
422306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
422406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
42254f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
422606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
422706656605SStefano Zampini       }
422806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
422906656605SStefano Zampini     }
423006656605SStefano Zampini   }
423180677318SStefano Zampini   if (n_constraints) {
423280677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
423380677318SStefano Zampini   }
42344f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
423572b8c272SStefano Zampini 
423672b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
423772b8c272SStefano Zampini   if (pcbddc->benign_n) {
423872b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
423972b8c272SStefano Zampini     IS          is_dummy;
424072b8c272SStefano Zampini     PetscScalar *data;
424172b8c272SStefano Zampini     PetscInt    j;
424272b8c272SStefano Zampini 
424372b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
42447dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
424572b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
424672b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
424786c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
424872b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
424972b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
425072b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
425172b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
425272b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
425372b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
425472b8c272SStefano Zampini       }
425572b8c272SStefano Zampini     }
425672b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
425772b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
425872b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
425972b8c272SStefano Zampini   }
4260019a44ceSStefano Zampini 
426106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
42623301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4263ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4264ffd830a3SStefano Zampini     PetscScalar *marray;
426506656605SStefano Zampini 
426606656605SStefano Zampini     if (n_constraints) {
4267ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
426806656605SStefano Zampini 
4269abc8f43dSstefano_zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
427006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
4271ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
427216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
427306656605SStefano Zampini       if (n_vertices) {
4274ffd830a3SStefano Zampini         Mat S_VCT;
427506656605SStefano Zampini 
427606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
4277ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
427816f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
427906656605SStefano Zampini       }
4280ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
42815b782168SStefano Zampini     } else {
42825b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
428306656605SStefano Zampini     }
428416f15bc4SStefano Zampini     if (n_vertices && n_R) {
4285ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4286ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4287ffd830a3SStefano Zampini       PetscInt       n;
4288ffd830a3SStefano Zampini       PetscBool      flg_row;
428906656605SStefano Zampini 
4290ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
4291af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
4292ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4293ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
4294ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4295ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4296ffd830a3SStefano Zampini         PetscInt j;
4297ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4298ffd830a3SStefano Zampini       }
4299ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4300ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4301ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
430206656605SStefano Zampini     }
430306656605SStefano Zampini 
4304ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4305abc8f43dSstefano_zampini     if (n_vertices) {
4306ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
4307ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
4308ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
4309ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
431006656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
431106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
431206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
431306656605SStefano Zampini       }
4314ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
4315abc8f43dSstefano_zampini     }
43165b782168SStefano Zampini     if (B_C) {
4317ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
4318ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
4319ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
4320ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
4321ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4322ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
4323ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
432406656605SStefano Zampini       }
4325ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
43265b782168SStefano Zampini     }
432706656605SStefano Zampini     /* coarse basis functions */
432806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
432906656605SStefano Zampini       PetscScalar *y;
433006656605SStefano Zampini 
4331ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
433206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
433306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
433406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
433506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
433606656605SStefano Zampini       if (i<n_vertices) {
433706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
433806656605SStefano Zampini       }
433906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
434006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
434106656605SStefano Zampini 
434206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
434306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
434406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
434506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
434606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
434706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
434806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
434906656605SStefano Zampini       }
435006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
435106656605SStefano Zampini     }
4352ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4353ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
435406656605SStefano Zampini   }
4355a6e023c1Sstefano_zampini 
4356d62866d3SStefano Zampini   /* free memory */
435788ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
435806656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
435906656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
436006656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
436106656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4362d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4363d62866d3SStefano Zampini   if (n_vertices) {
4364d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4365d62866d3SStefano Zampini   }
4366d62866d3SStefano Zampini   if (n_constraints) {
4367d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4368d62866d3SStefano Zampini   }
436988ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
437088ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
437188ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4372d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
437388ebb749SStefano Zampini     Mat         coarse_sub_mat;
437425084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
437588ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
437688ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
437788ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
43788bec7fa6SStefano Zampini     Mat         C_B,CPHI;
43798bec7fa6SStefano Zampini     IS          is_dummy;
43808bec7fa6SStefano Zampini     Vec         mones;
438188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
438288ebb749SStefano Zampini     PetscReal   real_value;
438388ebb749SStefano Zampini 
4384a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4385a3df083aSStefano Zampini       Mat A;
4386a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
43877dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
43887dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
43897dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
43907dae84e0SHong Zhang       ierr = MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4391a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4392a3df083aSStefano Zampini     } else {
439388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
439488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
439588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
439688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4397a3df083aSStefano Zampini     }
439888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
439988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4400ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
440188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
440288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
440388ebb749SStefano Zampini     }
440488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
440588ebb749SStefano Zampini 
440625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
44073301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
440825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4409ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
441088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
441188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
441288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
441388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
441488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
441588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
441688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
441788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
441888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
441988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
442088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
442188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
442288ebb749SStefano Zampini     } else {
442388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
442488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
442588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
442688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
442788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
442888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
442988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
443088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
443188ebb749SStefano Zampini     }
443288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
443388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
443488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4435511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
44364f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4437fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4438d12edf2fSStefano Zampini       PetscScalar *data,*data2;
44394f1b2e48SStefano Zampini       PetscInt    j;
4440d12edf2fSStefano Zampini 
44414f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44427dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4443d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
444486c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4445d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4446d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
44474f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
44484f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4449d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
44504f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
44514f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
44524f1b2e48SStefano Zampini         }
4453d12edf2fSStefano Zampini       }
4454d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4455d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4456d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4457d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4458d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4459d12edf2fSStefano Zampini     }
4460d12edf2fSStefano Zampini #if 0
4461d12edf2fSStefano Zampini   {
4462d12edf2fSStefano Zampini     PetscViewer viewer;
4463d12edf2fSStefano Zampini     char filename[256];
4464ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4465d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4466a7414863SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4467ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4468ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4469ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4470d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
4471a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
4472ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4473ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
447472b8c272SStefano Zampini     }
4475ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4476ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4477ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4478ffd830a3SStefano Zampini     }
4479ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4480ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4481ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4482ffd830a3SStefano Zampini     }
448372b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4484ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4485ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4486ffd830a3SStefano Zampini     }
4487d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4488d12edf2fSStefano Zampini   }
4489d12edf2fSStefano Zampini #endif
449081d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
44918bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
44921575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
449306656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
44948bec7fa6SStefano Zampini 
44958bec7fa6SStefano Zampini     /* check constraints */
4496a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
44977dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
44984f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
44998bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4500a00504b5SStefano Zampini     } else {
4501a00504b5SStefano Zampini       PetscScalar *data;
4502a00504b5SStefano Zampini       Mat         tmat;
4503a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4504a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4505a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4506a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4507a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4508a00504b5SStefano Zampini     }
45098bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
45108bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
45118bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
45128bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4513bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4514ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4515bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4516bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4517bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4518bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4519bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
452088ebb749SStefano Zampini     }
45218bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
45228bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
45238bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
45248bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
452525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
452688ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
452788ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
452888ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
452988ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
453088ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
453188ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
453288ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
453388ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
453488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
453588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4536ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
453788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
453888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
453988ebb749SStefano Zampini     }
454088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
454188ebb749SStefano Zampini   }
45428629588bSStefano Zampini   /* get back data */
45438629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
454488ebb749SStefano Zampini   PetscFunctionReturn(0);
454588ebb749SStefano Zampini }
454688ebb749SStefano Zampini 
45477dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4548aa0d41d4SStefano Zampini {
4549d65f70fdSStefano Zampini   Mat            *work_mat;
4550d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4551d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4552c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4553aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4554aa0d41d4SStefano Zampini 
4555aa0d41d4SStefano Zampini   PetscFunctionBegin;
4556d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4557d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4558d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4559d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4560aa0d41d4SStefano Zampini 
4561d65f70fdSStefano Zampini   if (!rsorted) {
4562906d46d4SStefano Zampini     const PetscInt *idxs;
4563906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4564aa0d41d4SStefano Zampini 
4565d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4566d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4567d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4568d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4569aa0d41d4SStefano Zampini     }
4570d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4571d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4572d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4573d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4574aa0d41d4SStefano Zampini     }
4575d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4576d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4577d65f70fdSStefano Zampini   } else {
4578d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4579d65f70fdSStefano Zampini     isrow_s = isrow;
4580aa0d41d4SStefano Zampini   }
4581906d46d4SStefano Zampini 
4582d65f70fdSStefano Zampini   if (!csorted) {
4583d65f70fdSStefano Zampini     if (isrow == iscol) {
4584d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4585d65f70fdSStefano Zampini       iscol_s = isrow_s;
4586d65f70fdSStefano Zampini     } else {
4587d65f70fdSStefano Zampini       const PetscInt *idxs;
4588d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4589906d46d4SStefano Zampini 
4590d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4591d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4592d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4593d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4594d65f70fdSStefano Zampini       }
4595d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4596d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4597d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4598d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4599d65f70fdSStefano Zampini       }
4600d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4601d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4602d65f70fdSStefano Zampini     }
4603d65f70fdSStefano Zampini   } else {
4604d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4605d65f70fdSStefano Zampini     iscol_s = iscol;
4606d65f70fdSStefano Zampini   }
4607d65f70fdSStefano Zampini 
46087dae84e0SHong Zhang   ierr = MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4609d65f70fdSStefano Zampini 
4610d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4611906d46d4SStefano Zampini     Mat      new_mat;
4612d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4613906d46d4SStefano Zampini 
4614d65f70fdSStefano Zampini     if (!rsorted) {
4615d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4616d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4617d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4618d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4619906d46d4SStefano Zampini       }
4620d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4621d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4622d65f70fdSStefano Zampini     } else {
4623d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4624906d46d4SStefano Zampini     }
4625d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4626d65f70fdSStefano Zampini 
4627d65f70fdSStefano Zampini     if (!csorted) {
4628d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4629d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4630d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4631d65f70fdSStefano Zampini       } else {
4632d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4633f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4634d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4635d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4636d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4637d65f70fdSStefano Zampini         }
4638d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4639d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4640d65f70fdSStefano Zampini       }
4641d65f70fdSStefano Zampini     } else {
4642d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4643d65f70fdSStefano Zampini     }
4644d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4645d65f70fdSStefano Zampini 
4646d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4647d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4648d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4649d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4650d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4651d65f70fdSStefano Zampini   }
4652d65f70fdSStefano Zampini 
4653d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4654d65f70fdSStefano Zampini   *B = work_mat[0];
4655d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4656d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4657d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4658d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4659d65f70fdSStefano Zampini }
4660d65f70fdSStefano Zampini 
46615e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4662aa0d41d4SStefano Zampini {
4663aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
46645e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4665022d8d2bSstefano_zampini   Mat            new_mat,lA;
46665e8657edSStefano Zampini   IS             is_local,is_global;
4667d65f70fdSStefano Zampini   PetscInt       local_size;
4668d65f70fdSStefano Zampini   PetscBool      isseqaij;
4669aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4670aa0d41d4SStefano Zampini 
4671aa0d41d4SStefano Zampini   PetscFunctionBegin;
4672aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
46735e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
46745e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4675b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4676aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
46777dae84e0SHong Zhang   ierr = MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4678aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4679906d46d4SStefano Zampini 
4680906d46d4SStefano Zampini   /* check */
4681906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4682906d46d4SStefano Zampini     Vec       x,x_change;
4683906d46d4SStefano Zampini     PetscReal error;
4684906d46d4SStefano Zampini 
46855e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4686906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
46875e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4688e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4689e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4690d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
469188428137SStefano Zampini     if (!pcbddc->change_interior) {
469288428137SStefano Zampini       const PetscScalar *x,*y,*v;
469388428137SStefano Zampini       PetscReal         lerror = 0.;
469488428137SStefano Zampini       PetscInt          i;
469588428137SStefano Zampini 
469688428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
469788428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
469888428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
469988428137SStefano Zampini       for (i=0;i<local_size;i++)
470088428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
470188428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
470288428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
470388428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
470488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
470588428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4706637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4707637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4708637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4709637e8532SStefano Zampini         } else {
4710637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4711637e8532SStefano Zampini         }
4712637e8532SStefano Zampini       }
471388428137SStefano Zampini     }
4714e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4715e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4716906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4717906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4718637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4719637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4720637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4721637e8532SStefano Zampini       } else {
4722637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4723637e8532SStefano Zampini       }
4724637e8532SStefano Zampini     }
4725906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4726906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4727906d46d4SStefano Zampini   }
4728906d46d4SStefano Zampini 
4729022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
4730022d8d2bSstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
4731022d8d2bSstefano_zampini 
473222d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
47339b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
473422d5777bSStefano Zampini   if (isseqaij) {
4735a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4736a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4737022d8d2bSstefano_zampini     if (lA) {
4738022d8d2bSstefano_zampini       Mat work;
4739022d8d2bSstefano_zampini       ierr = MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4740022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4741022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4742022d8d2bSstefano_zampini     }
4743aa0d41d4SStefano Zampini   } else {
4744a00504b5SStefano Zampini     Mat work_mat;
47451cf9b237SStefano Zampini 
4746a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4747aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4748a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
47491d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4750022d8d2bSstefano_zampini     if (lA) {
4751022d8d2bSstefano_zampini       Mat work;
4752022d8d2bSstefano_zampini       ierr = MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4753022d8d2bSstefano_zampini       ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work);CHKERRQ(ierr);
4754022d8d2bSstefano_zampini       ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work);CHKERRQ(ierr);
4755022d8d2bSstefano_zampini       ierr = MatDestroy(&work);CHKERRQ(ierr);
4756022d8d2bSstefano_zampini     }
4757aa0d41d4SStefano Zampini   }
47583301b35fSStefano Zampini   if (matis->A->symmetric_set) {
47593301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4760e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
47613301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4762e496cd5dSStefano Zampini #endif
47633301b35fSStefano Zampini   }
4764d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4765aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4766aa0d41d4SStefano Zampini }
4767aa0d41d4SStefano Zampini 
47688ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4769a64d13efSStefano Zampini {
4770a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4771a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4772d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
477353892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
47743a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
47753a50541eSStefano Zampini   PetscInt        vbs,bs;
47766816873aSStefano Zampini   PetscBT         bitmask=NULL;
4777a64d13efSStefano Zampini   PetscErrorCode  ierr;
4778a64d13efSStefano Zampini 
4779a64d13efSStefano Zampini   PetscFunctionBegin;
4780b23d619eSStefano Zampini   /*
4781b23d619eSStefano Zampini     No need to setup local scatters if
4782b23d619eSStefano Zampini       - primal space is unchanged
4783b23d619eSStefano Zampini         AND
4784b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4785b23d619eSStefano Zampini         AND
4786b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4787b23d619eSStefano Zampini   */
4788b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4789f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4790f4ddd8eeSStefano Zampini   }
4791f4ddd8eeSStefano Zampini   /* destroy old objects */
4792f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4793f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4794f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4795a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4796b371cd4fSStefano Zampini   n_B = pcis->n_B;
4797b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4798b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
47993a50541eSStefano Zampini 
4800a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
48016816873aSStefano Zampini 
480253892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4803b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4804854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4805a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4806a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
48070e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4808a64d13efSStefano Zampini     }
4809a64d13efSStefano Zampini 
4810a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
48114641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
48126816873aSStefano Zampini         idx_R_local[n_R++] = i;
4813a64d13efSStefano Zampini       }
4814a64d13efSStefano Zampini     }
4815df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4816df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
48176816873aSStefano Zampini 
4818df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4819df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
48206816873aSStefano Zampini   }
48213a50541eSStefano Zampini 
48223a50541eSStefano Zampini   /* Block code */
48233a50541eSStefano Zampini   vbs = 1;
48243a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
48253a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
48263a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
48273a50541eSStefano Zampini     PetscInt  *vary;
4828b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4829785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
48303a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4831d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4832d3df7717SStefano 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 */
48330e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4834d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
48353a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
48363a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
48373a50541eSStefano Zampini           break;
48383a50541eSStefano Zampini         }
48393a50541eSStefano Zampini       }
4840d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4841d3df7717SStefano Zampini     } else {
4842d3df7717SStefano Zampini       /* Verify directly the R set */
4843d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4844d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4845d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4846d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4847d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4848d3df7717SStefano Zampini             break;
4849d3df7717SStefano Zampini           }
4850d3df7717SStefano Zampini         }
4851d3df7717SStefano Zampini       }
4852d3df7717SStefano Zampini     }
48533a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
48543a50541eSStefano Zampini       vbs = bs;
48553a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
48563a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
48573a50541eSStefano Zampini       }
48583a50541eSStefano Zampini     }
48593a50541eSStefano Zampini   }
48603a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4861b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4862df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
486353892102SStefano Zampini 
4864df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4865df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
486653892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4867df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
486853892102SStefano Zampini   } else {
48693a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
487053892102SStefano Zampini   }
4871a64d13efSStefano Zampini 
4872a64d13efSStefano Zampini   /* print some info if requested */
4873a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4874a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4875a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
48761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4877a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4878a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
48794f1b2e48SStefano 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);
4880a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4881a64d13efSStefano Zampini   }
4882a64d13efSStefano Zampini 
4883a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4884b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
48856816873aSStefano Zampini     IS       is_aux1,is_aux2;
48866816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
48876816873aSStefano Zampini 
48883a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4889854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4890854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4891a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
48924641a718SStefano Zampini     for (i=0; i<n_D; i++) {
48934641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
48944641a718SStefano Zampini     }
4895a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4896a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
48974641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
48984641a718SStefano Zampini         aux_array1[j++] = i;
4899a64d13efSStefano Zampini       }
4900a64d13efSStefano Zampini     }
4901a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4902a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4903a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
49044641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
49054641a718SStefano Zampini         aux_array2[j++] = i;
4906a64d13efSStefano Zampini       }
4907a64d13efSStefano Zampini     }
4908a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4909a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4910a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4911a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4912a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4913a64d13efSStefano Zampini 
49148eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4915785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4916a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
49174641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
49184641a718SStefano Zampini           aux_array1[j++] = i;
4919a64d13efSStefano Zampini         }
4920a64d13efSStefano Zampini       }
4921a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4922a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4923a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4924a64d13efSStefano Zampini     }
49254641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
49263a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4927d62866d3SStefano Zampini   } else {
4928df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
49296816873aSStefano Zampini     IS                 tis;
49306816873aSStefano Zampini     PetscInt           schur_size;
49316816873aSStefano Zampini 
4932df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
49336816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4934df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
49356816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
49366816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
49376816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
49386816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
49396816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4940d62866d3SStefano Zampini     }
4941d62866d3SStefano Zampini   }
4942a64d13efSStefano Zampini   PetscFunctionReturn(0);
4943a64d13efSStefano Zampini }
4944a64d13efSStefano Zampini 
4945304d26faSStefano Zampini 
4946684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4947304d26faSStefano Zampini {
4948304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4949304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4950304d26faSStefano Zampini   PC             pc_temp;
4951304d26faSStefano Zampini   Mat            A_RR;
4952f4ddd8eeSStefano Zampini   MatReuse       reuse;
4953304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4954304d26faSStefano Zampini   PetscReal      value;
495504708bb6SStefano Zampini   PetscInt       n_D,n_R;
495635529e7bSStefano Zampini   PetscBool      check_corr,issbaij;
4957304d26faSStefano Zampini   PetscErrorCode ierr;
4958e604994aSStefano Zampini   /* prefixes stuff */
4959312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4960e604994aSStefano Zampini   size_t         len;
4961304d26faSStefano Zampini 
4962304d26faSStefano Zampini   PetscFunctionBegin;
4963304d26faSStefano Zampini 
4964e604994aSStefano Zampini   /* compute prefixes */
4965e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4966e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4967e604994aSStefano Zampini   if (!pcbddc->current_level) {
4968e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4969e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4970e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4971e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4972e604994aSStefano Zampini   } else {
497335529e7bSStefano Zampini     ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
4974e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4975e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4976312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4977312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
497834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
497934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4980e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4981e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4982e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4983e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4984e604994aSStefano Zampini   }
4985e604994aSStefano Zampini 
4986304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4987684f6988SStefano Zampini   if (dirichlet) {
4988d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4989450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
49909a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4991450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4992a3df083aSStefano Zampini         Mat    A_IIn;
4993a3df083aSStefano Zampini 
4994a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4995a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4996a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4997a3df083aSStefano Zampini       }
4998450f8f5eSStefano Zampini     }
49993301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
50003301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
5001964fefecSStefano Zampini     }
5002ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5003964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
5004304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
5005304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
5006304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
5007304d26faSStefano Zampini       /* default */
5008304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
5009e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
50109577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
5011304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
50129577ea80SStefano Zampini       if (issbaij) {
50139577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
50149577ea80SStefano Zampini       } else {
5015304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
50169577ea80SStefano Zampini       }
5017304d26faSStefano Zampini       /* Allow user's customization */
5018304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
5019304d26faSStefano Zampini     }
5020d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
5021b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5022df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5023d62866d3SStefano Zampini 
5024df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
5025d5574798SStefano Zampini     }
5026304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5027304d26faSStefano Zampini     if (!n_D) {
5028304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
5029304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5030304d26faSStefano Zampini     }
5031304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
5032304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
5033304d26faSStefano Zampini     /* set ksp_D into pcis data */
5034304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
5035304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
5036304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5037684f6988SStefano Zampini   }
5038304d26faSStefano Zampini 
5039304d26faSStefano Zampini   /* NEUMANN PROBLEM */
5040684f6988SStefano Zampini   A_RR = 0;
5041684f6988SStefano Zampini   if (neumann) {
5042d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
504304708bb6SStefano Zampini     PetscInt        ibs,mbs;
50440aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
504504708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
50460aa714b2SStefano Zampini 
50470aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
50480aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
50490aa714b2SStefano Zampini       IS iP;
50500aa714b2SStefano Zampini 
50510aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
50520aa714b2SStefano Zampini       ierr = PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
50530aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
50540aa714b2SStefano Zampini     }
5055f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
50568ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
5057f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5058f4ddd8eeSStefano Zampini       PetscInt nn_R;
505981d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
5060f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5061f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
5062f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
5063f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
5064f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5065f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5066f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5067727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
5068f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5069f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5070f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5071f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5072f4ddd8eeSStefano Zampini         }
5073f4ddd8eeSStefano Zampini       }
5074f4ddd8eeSStefano Zampini       /* last check */
5075d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
5076f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5077f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5078f4ddd8eeSStefano Zampini       }
5079f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5080f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5081f4ddd8eeSStefano Zampini     }
5082a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
5083af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
5084af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
508504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
508604708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
508704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
508804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
508904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5090af732b37SStefano Zampini       } else {
5091511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
50926816873aSStefano Zampini       }
509304708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
509404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
509504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
509604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
509704708bb6SStefano Zampini       } else {
5098511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
509904708bb6SStefano Zampini       }
510004708bb6SStefano Zampini     }
5101a00504b5SStefano Zampini     /* extract A_RR */
51020aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5103a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5104a00504b5SStefano Zampini 
5105a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
510616e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5107a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
510816e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
510916e386b8SStefano Zampini         } else {
51107dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
5111a00504b5SStefano Zampini         }
5112a00504b5SStefano Zampini       } else {
5113a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5114a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
5115a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
5116a00504b5SStefano Zampini       }
5117a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
51187dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
511916e386b8SStefano Zampini     }
51203301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
51213301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
51226816873aSStefano Zampini     }
5123f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
5124304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
5125304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
5126304d26faSStefano Zampini       /* default */
5127304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
5128e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
5129304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
51309577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
51319577ea80SStefano Zampini       if (issbaij) {
51329577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
51339577ea80SStefano Zampini       } else {
5134304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
51359577ea80SStefano Zampini       }
5136304d26faSStefano Zampini       /* Allow user's customization */
5137304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
5138304d26faSStefano Zampini     }
5139304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5140304d26faSStefano Zampini     if (!n_R) {
5141304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
5142304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
5143304d26faSStefano Zampini     }
51445cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
5145df4d28bfSStefano Zampini     /* Reuse solver if it is present */
51460aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5147df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5148d62866d3SStefano Zampini 
5149df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
5150d62866d3SStefano Zampini     }
5151304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
5152304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
5153684f6988SStefano Zampini   }
5154304d26faSStefano Zampini 
5155684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
5156684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51571575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5158684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5159684f6988SStefano Zampini   }
5160c7017625SStefano Zampini 
5161c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
516235529e7bSStefano Zampini   check_corr = PETSC_FALSE;
5163c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
5164c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
5165c7017625SStefano Zampini   }
5166c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
516735529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5168c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
5169c7017625SStefano Zampini   }
5170c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
517135529e7bSStefano Zampini     check_corr = PETSC_TRUE;
5172c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
5173c7017625SStefano Zampini   }
5174c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5175c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5176684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
51770fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
51780fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
51790fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
51800fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
51810fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
5182e604994aSStefano 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);
518335529e7bSStefano Zampini       if (check_corr) {
5184c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
5185c7017625SStefano Zampini       }
5186304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5187304d26faSStefano Zampini     }
5188684f6988SStefano Zampini     if (neumann) { /* Neumann */
51890fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
51900fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
51910fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
51920fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
51930fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
5194e604994aSStefano 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);
519535529e7bSStefano Zampini       if (check_corr) {
5196c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
5197c7017625SStefano Zampini       }
5198304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5199304d26faSStefano Zampini     }
5200684f6988SStefano Zampini   }
52015cbda25cSStefano Zampini   /* free Neumann problem's matrix */
52025cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
5203304d26faSStefano Zampini   PetscFunctionReturn(0);
5204304d26faSStefano Zampini }
5205304d26faSStefano Zampini 
520680677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5207674ae819SStefano Zampini {
5208674ae819SStefano Zampini   PetscErrorCode  ierr;
5209674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5210be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5211b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
5212674ae819SStefano Zampini 
5213674ae819SStefano Zampini   PetscFunctionBegin;
5214b334f244SStefano Zampini   if (!reuse_solver) {
521580677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
521620c7b377SStefano Zampini   }
521780677318SStefano Zampini   if (!pcbddc->switch_static) {
521880677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
521980677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
522080677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
522120c7b377SStefano Zampini     }
5222b334f244SStefano Zampini     if (!reuse_solver) {
522380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
522480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
522520c7b377SStefano Zampini     } else {
5226df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5227be83ff47SStefano Zampini 
5228df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5229df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
523020c7b377SStefano Zampini     }
5231be83ff47SStefano Zampini   } else {
523280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
523380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
523480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
523580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
523680677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
523780677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
523880677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
523980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
524080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5241674ae819SStefano Zampini     }
5242674ae819SStefano Zampini   }
5243b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
524480677318SStefano Zampini     if (applytranspose) {
524580677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
524680677318SStefano Zampini     } else {
524780677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
524880677318SStefano Zampini     }
5249be83ff47SStefano Zampini   } else {
5250df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5251be83ff47SStefano Zampini 
5252be83ff47SStefano Zampini     if (applytranspose) {
5253df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5254be83ff47SStefano Zampini     } else {
5255df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
5256be83ff47SStefano Zampini     }
5257be83ff47SStefano Zampini   }
525880677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
525980677318SStefano Zampini   if (!pcbddc->switch_static) {
5260b334f244SStefano Zampini     if (!reuse_solver) {
526180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
526280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5263be83ff47SStefano Zampini     } else {
5264df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5265be83ff47SStefano Zampini 
5266df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5267df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5268be83ff47SStefano Zampini     }
526980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
527080677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
527180677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
527280677318SStefano Zampini     }
527380677318SStefano Zampini   } else {
527480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
527580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
527680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
527780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
527880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
527980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
528080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
528180677318SStefano Zampini     }
528280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
528380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
528480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
528580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5286674ae819SStefano Zampini   }
5287674ae819SStefano Zampini   PetscFunctionReturn(0);
5288674ae819SStefano Zampini }
5289674ae819SStefano Zampini 
5290dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5291dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5292674ae819SStefano Zampini {
5293674ae819SStefano Zampini   PetscErrorCode ierr;
5294674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5295674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5296674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5297674ae819SStefano Zampini 
5298674ae819SStefano Zampini   PetscFunctionBegin;
5299d4a6ed37SStefano Zampini   PetscBool ss = PETSC_FALSE;
5300d4a6ed37SStefano Zampini   ierr = PetscOptionsGetBool(NULL,NULL,"-swap",&ss,NULL);CHKERRQ(ierr);
5301d4a6ed37SStefano Zampini   if (ss) {
5302d4a6ed37SStefano Zampini   Mat save_B = pcbddc->coarse_phi_B;
5303d4a6ed37SStefano Zampini   pcbddc->coarse_phi_B = pcbddc->coarse_psi_B;
5304d4a6ed37SStefano Zampini   pcbddc->coarse_psi_B = save_B;
5305d4a6ed37SStefano Zampini   Mat save_D = pcbddc->coarse_phi_D;
5306d4a6ed37SStefano Zampini   pcbddc->coarse_phi_D = pcbddc->coarse_psi_D;
5307d4a6ed37SStefano Zampini   pcbddc->coarse_psi_D = save_D;
5308d4a6ed37SStefano Zampini   }
5309dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
53104fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5311dc359a40SStefano Zampini     if (applytranspose) {
5312674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
53138eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
5314dc359a40SStefano Zampini     } else {
5315674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
5316674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
531715aaf578SStefano Zampini     }
53184fee134fSStefano Zampini   } else {
53194fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
53204fee134fSStefano Zampini   }
5321efc2fbd9SStefano Zampini 
5322efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
53234f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5324efc2fbd9SStefano Zampini     PetscScalar *array;
53254f1b2e48SStefano Zampini     PetscInt    j;
5326efc2fbd9SStefano Zampini 
5327efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
53284f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
5329efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5330efc2fbd9SStefano Zampini   }
5331efc2fbd9SStefano Zampini 
533212edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
533312edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
533412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
533512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
533612edc857SStefano Zampini 
53379f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
533812edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
533951694757SStefano Zampini     Mat          coarse_mat;
5340964fefecSStefano Zampini     Vec          rhs,sol;
534151694757SStefano Zampini     MatNullSpace nullsp;
534227b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5343964fefecSStefano Zampini 
534427b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
534527b6a85dSStefano Zampini       PC        coarse_pc;
534627b6a85dSStefano Zampini 
534727b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
534827b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
534927b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
535027b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
535127b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
535227b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
53533bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
535427b6a85dSStefano Zampini       }
535527b6a85dSStefano Zampini     }
5356964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5357964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
535851694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
535951694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
536051694757SStefano Zampini     if (nullsp) {
536151694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
536251694757SStefano Zampini     }
536312edc857SStefano Zampini     if (applytranspose) {
53649a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5365964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
53662701bc32SStefano Zampini     } else {
53671f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
53682701bc32SStefano Zampini         PC        coarse_pc;
53692701bc32SStefano Zampini 
53702701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
53712701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
53723e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
53732701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
537412edc857SStefano Zampini       } else {
5375964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
537612edc857SStefano Zampini       }
53772701bc32SStefano Zampini     }
53781d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
537927b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
538027b6a85dSStefano Zampini       PC        coarse_pc;
538127b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
538227b6a85dSStefano Zampini 
538327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
538427b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
538527b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
53863bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
538727b6a85dSStefano Zampini     }
538851694757SStefano Zampini     if (nullsp) {
538951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
539051694757SStefano Zampini     }
539112edc857SStefano Zampini   }
5392674ae819SStefano Zampini 
5393674ae819SStefano Zampini   /* Local solution on R nodes */
53944fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
539580677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
53969f00e9b4SStefano Zampini   }
53979f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
53989f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
539912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5400674ae819SStefano Zampini 
54014fee134fSStefano Zampini   /* Sum contributions from the two levels */
54024fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5403dc359a40SStefano Zampini     if (applytranspose) {
5404dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5405dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5406dc359a40SStefano Zampini     } else {
5407674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
54088eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5409dc359a40SStefano Zampini     }
5410efc2fbd9SStefano Zampini     /* store p0 */
54114f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5412efc2fbd9SStefano Zampini       PetscScalar *array;
54134f1b2e48SStefano Zampini       PetscInt    j;
5414efc2fbd9SStefano Zampini 
5415efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
54164f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5417efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5418efc2fbd9SStefano Zampini     }
54194fee134fSStefano Zampini   } else { /* expand the coarse solution */
54204fee134fSStefano Zampini     if (applytranspose) {
54214fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
54224fee134fSStefano Zampini     } else {
54234fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
54244fee134fSStefano Zampini     }
54254fee134fSStefano Zampini   }
5426d4a6ed37SStefano Zampini   if (ss) {
5427d4a6ed37SStefano Zampini   Mat save_B = pcbddc->coarse_phi_B;
5428d4a6ed37SStefano Zampini   pcbddc->coarse_phi_B = pcbddc->coarse_psi_B;
5429d4a6ed37SStefano Zampini   pcbddc->coarse_psi_B = save_B;
5430d4a6ed37SStefano Zampini   Mat save_D = pcbddc->coarse_phi_D;
5431d4a6ed37SStefano Zampini   pcbddc->coarse_phi_D = pcbddc->coarse_psi_D;
5432d4a6ed37SStefano Zampini   pcbddc->coarse_psi_D = save_D;
5433d4a6ed37SStefano Zampini   }
5434674ae819SStefano Zampini   PetscFunctionReturn(0);
5435674ae819SStefano Zampini }
5436674ae819SStefano Zampini 
543712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5438674ae819SStefano Zampini {
5439674ae819SStefano Zampini   PetscErrorCode ierr;
5440674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
544158da7f69SStefano Zampini   PetscScalar    *array;
544212edc857SStefano Zampini   Vec            from,to;
5443674ae819SStefano Zampini 
5444674ae819SStefano Zampini   PetscFunctionBegin;
544512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
544612edc857SStefano Zampini     from = pcbddc->coarse_vec;
544712edc857SStefano Zampini     to = pcbddc->vec1_P;
544812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
544912edc857SStefano Zampini       Vec tvec;
545058da7f69SStefano Zampini 
545158da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
545258da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
545312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
545458da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
545558da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
545658da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
545712edc857SStefano Zampini     }
545812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
545912edc857SStefano Zampini     from = pcbddc->vec1_P;
546012edc857SStefano Zampini     to = pcbddc->coarse_vec;
546112edc857SStefano Zampini   }
546212edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5463674ae819SStefano Zampini   PetscFunctionReturn(0);
5464674ae819SStefano Zampini }
5465674ae819SStefano Zampini 
546612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5467674ae819SStefano Zampini {
5468674ae819SStefano Zampini   PetscErrorCode ierr;
5469674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
547058da7f69SStefano Zampini   PetscScalar    *array;
547112edc857SStefano Zampini   Vec            from,to;
5472674ae819SStefano Zampini 
5473674ae819SStefano Zampini   PetscFunctionBegin;
547412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
547512edc857SStefano Zampini     from = pcbddc->coarse_vec;
547612edc857SStefano Zampini     to = pcbddc->vec1_P;
547712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
547812edc857SStefano Zampini     from = pcbddc->vec1_P;
547912edc857SStefano Zampini     to = pcbddc->coarse_vec;
548012edc857SStefano Zampini   }
548112edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
548212edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
548312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
548412edc857SStefano Zampini       Vec tvec;
548558da7f69SStefano Zampini 
548612edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
548758da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
548858da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
548958da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
549058da7f69SStefano Zampini     }
549158da7f69SStefano Zampini   } else {
549258da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
549358da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
549412edc857SStefano Zampini     }
549512edc857SStefano Zampini   }
5496674ae819SStefano Zampini   PetscFunctionReturn(0);
5497674ae819SStefano Zampini }
5498674ae819SStefano Zampini 
5499984c4197SStefano Zampini /* uncomment for testing purposes */
5500984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5501674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5502674ae819SStefano Zampini {
5503674ae819SStefano Zampini   PetscErrorCode    ierr;
5504674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5505674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5506674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5507984c4197SStefano Zampini   /* one and zero */
5508984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5509984c4197SStefano Zampini   /* space to store constraints and their local indices */
55109162d606SStefano Zampini   PetscScalar       *constraints_data;
55119162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
55129162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
55139162d606SStefano Zampini   PetscInt          *constraints_n;
5514984c4197SStefano Zampini   /* iterators */
5515b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5516984c4197SStefano Zampini   /* BLAS integers */
5517e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5518e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5519c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5520727cdba6SStefano Zampini   /* reuse */
55210e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
55220e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5523984c4197SStefano Zampini   /* change of basis */
5524b3d85658SStefano Zampini   PetscBool         qr_needed;
55259162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5526984c4197SStefano Zampini   /* auxiliary stuff */
552764efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
55288a0068c3SStefano Zampini   PetscInt          ncc;
5529984c4197SStefano Zampini   /* some quantities */
553045a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5531a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
5532984c4197SStefano Zampini 
5533674ae819SStefano Zampini   PetscFunctionBegin;
55348e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
55358e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
55368e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
553716909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5538088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5539088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
55400e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
55410e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
55420e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
55430e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
55440e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5545088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5546cf5a6209SStefano Zampini 
5547cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
55489162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5549cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5550cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5551cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5552cf5a6209SStefano Zampini     PetscScalar  *array;
5553cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5554cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5555674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5556b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5557674ae819SStefano Zampini     PetscScalar  *work;
5558674ae819SStefano Zampini     PetscReal    *singular_vals;
5559674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5560674ae819SStefano Zampini     PetscReal    *rwork;
5561674ae819SStefano Zampini #endif
5562674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5563674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5564674ae819SStefano Zampini #else
5565964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5566964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5567674ae819SStefano Zampini #endif
5568674ae819SStefano Zampini 
5569674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5570d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5571e4d548c7SStefano Zampini     /* print some info */
55725c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5573e4d548c7SStefano Zampini       PetscInt nv;
5574e4d548c7SStefano Zampini 
5575c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5576e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5577e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5578e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5579e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5580e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5581e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5582e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5583e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5584e4d548c7SStefano Zampini     }
5585e4d548c7SStefano Zampini 
5586d06fc5fdSStefano Zampini     /* free unneeded index sets */
5587d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5588d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5589674ae819SStefano Zampini     }
5590d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5591d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5592d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5593d06fc5fdSStefano Zampini       }
5594d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5595d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5596d06fc5fdSStefano Zampini     }
5597d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5598d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5599d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5600d06fc5fdSStefano Zampini       }
5601d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5602d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5603d06fc5fdSStefano Zampini     }
560470022509SStefano Zampini 
5605674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5606674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5607674ae819SStefano Zampini     if (nearnullsp) {
5608674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5609f4ddd8eeSStefano Zampini       /* remove any stored info */
5610f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5611f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5612f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5613f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5614f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5615473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5616f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5617f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5618f4ddd8eeSStefano Zampini       }
5619984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5620984c4197SStefano Zampini       nnsp_size = 0;
5621674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5622674ae819SStefano Zampini     }
5623984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5624984c4197SStefano Zampini     max_constraints = nnsp_size;
5625984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5626984c4197SStefano Zampini 
5627674ae819SStefano Zampini     /*
5628674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
56299162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
56309162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
56319162d606SStefano Zampini          There can be multiple constraints per connected component
5632674ae819SStefano Zampini                                                                                                                                                            */
5633674ae819SStefano Zampini     n_vertices = 0;
5634674ae819SStefano Zampini     if (ISForVertices) {
5635674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5636674ae819SStefano Zampini     }
56379162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
56389162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
56399162d606SStefano Zampini 
56409162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
56419162d606SStefano Zampini     total_counts *= max_constraints;
5642674ae819SStefano Zampini     total_counts += n_vertices;
56434641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
56449162d606SStefano Zampini 
5645674ae819SStefano Zampini     total_counts = 0;
5646674ae819SStefano Zampini     max_size_of_constraint = 0;
5647674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
56489162d606SStefano Zampini       IS used_is;
5649674ae819SStefano Zampini       if (i<n_ISForEdges) {
56509162d606SStefano Zampini         used_is = ISForEdges[i];
5651674ae819SStefano Zampini       } else {
56529162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5653674ae819SStefano Zampini       }
56549162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5655674ae819SStefano Zampini       total_counts += j;
5656674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5657674ae819SStefano Zampini     }
56589162d606SStefano 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);
56599162d606SStefano Zampini 
5660984c4197SStefano Zampini     /* get local part of global near null space vectors */
5661785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5662984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5663984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5664e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5665e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5666984c4197SStefano Zampini     }
5667674ae819SStefano Zampini 
5668242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5669242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5670a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5671242a89d7SStefano Zampini 
5672984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5673a773dcb8SStefano Zampini     if (!skip_lapack) {
5674674ae819SStefano Zampini       PetscScalar temp_work;
5675911cabfeSStefano Zampini 
5676674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5677984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5678785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5679785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5680785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5681674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5682785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5683674ae819SStefano Zampini #endif
5684674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5685c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5686c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5687674ae819SStefano Zampini       lwork = -1;
5688674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5689674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5690c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5691674ae819SStefano Zampini #else
5692c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5693674ae819SStefano Zampini #endif
5694674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5695984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5696674ae819SStefano Zampini #else /* on missing GESVD */
5697674ae819SStefano Zampini       /* SVD */
5698674ae819SStefano Zampini       PetscInt max_n,min_n;
5699674ae819SStefano Zampini       max_n = max_size_of_constraint;
5700984c4197SStefano Zampini       min_n = max_constraints;
5701984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5702674ae819SStefano Zampini         min_n = max_size_of_constraint;
5703984c4197SStefano Zampini         max_n = max_constraints;
5704674ae819SStefano Zampini       }
5705785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5706674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5707785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5708674ae819SStefano Zampini #endif
5709674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5710674ae819SStefano Zampini       lwork = -1;
5711e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5712e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5713b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5714674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5715674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
57169162d606SStefano 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));
5717674ae819SStefano Zampini #else
57189162d606SStefano 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));
5719674ae819SStefano Zampini #endif
5720674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5721984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5722984c4197SStefano Zampini #endif /* on missing GESVD */
5723674ae819SStefano Zampini       /* Allocate optimal workspace */
5724674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5725854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5726674ae819SStefano Zampini     }
5727674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5728674ae819SStefano Zampini     total_counts = 0;
57299162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
57309162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5731674ae819SStefano Zampini     /* vertices */
57329162d606SStefano Zampini     if (n_vertices) {
5733674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
57349162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5735674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
57369162d606SStefano Zampini         constraints_n[total_counts] = 1;
57379162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
57389162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
57399162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5740674ae819SStefano Zampini         total_counts++;
5741674ae819SStefano Zampini       }
5742674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5743674ae819SStefano Zampini       n_vertices = total_counts;
5744674ae819SStefano Zampini     }
5745984c4197SStefano Zampini 
5746674ae819SStefano Zampini     /* edges and faces */
57479162d606SStefano Zampini     total_counts_cc = total_counts;
5748911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
57499162d606SStefano Zampini       IS        used_is;
57509162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
57519162d606SStefano Zampini 
5752911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
57539162d606SStefano Zampini         used_is = ISForEdges[ncc];
5754984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5755674ae819SStefano Zampini       } else {
57569162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5757984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5758674ae819SStefano Zampini       }
5759674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
57609162d606SStefano Zampini 
57619162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
57629162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5763984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5764984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5765674ae819SStefano Zampini       if (nnsp_has_cnst) {
57665b08dc53SStefano Zampini         PetscScalar quad_value;
57679162d606SStefano Zampini 
57689162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
57699162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
57709162d606SStefano Zampini 
5771a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5772674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5773a773dcb8SStefano Zampini         } else {
5774a773dcb8SStefano Zampini           quad_value = 1.0;
5775a773dcb8SStefano Zampini         }
5776674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
57779162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5778674ae819SStefano Zampini         }
57799162d606SStefano Zampini         temp_constraints++;
5780674ae819SStefano Zampini         total_counts++;
5781674ae819SStefano Zampini       }
5782674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5783984c4197SStefano Zampini         PetscReal real_value;
57849162d606SStefano Zampini         PetscScalar *ptr_to_data;
57859162d606SStefano Zampini 
5786984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
57879162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5788674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
57899162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5790674ae819SStefano Zampini         }
5791984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5792984c4197SStefano Zampini         /* check if array is null on the connected component */
5793e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
57949162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
57955b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5796674ae819SStefano Zampini           temp_constraints++;
5797674ae819SStefano Zampini           total_counts++;
57989162d606SStefano Zampini           if (!idxs_copied) {
57999162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
58009162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5801674ae819SStefano Zampini           }
5802674ae819SStefano Zampini         }
58039162d606SStefano Zampini       }
58049162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
580545a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5806eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5807a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
58089162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
58099162d606SStefano Zampini 
58109162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5811a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
58129162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5813a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
58149162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5815a773dcb8SStefano Zampini         } else { /* perform SVD */
5816984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
58179162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5818674ae819SStefano Zampini 
5819674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5820984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5821984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5822984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5823984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5824984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5825984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5826984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5827984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5828674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5829e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5830984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5831674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5832674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
58339162d606SStefano 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));
5834674ae819SStefano Zampini             }
5835674ae819SStefano Zampini           }
5836e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5837e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5838e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5839674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5840c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5841674ae819SStefano Zampini #else
5842c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5843674ae819SStefano Zampini #endif
5844674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5845984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5846984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5847674ae819SStefano Zampini           j = 0;
5848984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5849674ae819SStefano Zampini           total_counts = total_counts-j;
585045a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5851e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5852c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5853c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5854c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5855c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5856c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5857c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5858674ae819SStefano Zampini           if (j<temp_constraints) {
5859984c4197SStefano Zampini             PetscInt ii;
5860984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5861674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58629162d606SStefano 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));
5863674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5864984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5865674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
58669162d606SStefano 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];
5867674ae819SStefano Zampini               }
5868674ae819SStefano Zampini             }
5869674ae819SStefano Zampini           }
5870674ae819SStefano Zampini #else  /* on missing GESVD */
5871e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5872e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5873b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5874674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5875674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
58769162d606SStefano 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));
5877674ae819SStefano Zampini #else
58789162d606SStefano 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));
5879674ae819SStefano Zampini #endif
5880984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5881674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5882984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5883e310c8b4SStefano Zampini           k = temp_constraints;
5884e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5885674ae819SStefano Zampini           j = 0;
5886e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
588745a1bb75SStefano Zampini           valid_constraints = k-j;
5888911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5889984c4197SStefano Zampini #endif /* on missing GESVD */
5890674ae819SStefano Zampini         }
5891a773dcb8SStefano Zampini       }
58929162d606SStefano Zampini       /* update pointers information */
58939162d606SStefano Zampini       if (valid_constraints) {
58949162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
58959162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
58969162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
58979162d606SStefano Zampini         /* set change_of_basis flag */
589845a1bb75SStefano Zampini         if (boolforchange) {
5899b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
59009162d606SStefano Zampini         }
5901b3d85658SStefano Zampini         total_counts_cc++;
590245a1bb75SStefano Zampini       }
590345a1bb75SStefano Zampini     }
5904984c4197SStefano Zampini     /* free workspace */
59058f1c130eSStefano Zampini     if (!skip_lapack) {
5906984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5907984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5908984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5909984c4197SStefano Zampini #endif
5910984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5911984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5912984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5913984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5914984c4197SStefano Zampini #endif
5915984c4197SStefano Zampini     }
5916984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5917984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5918984c4197SStefano Zampini     }
5919984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5920cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5921cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5922cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5923cf5a6209SStefano Zampini     }
5924cf5a6209SStefano Zampini     if (n_ISForFaces) {
5925cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5926cf5a6209SStefano Zampini     }
5927cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5928cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5929cf5a6209SStefano Zampini     }
5930cf5a6209SStefano Zampini     if (n_ISForEdges) {
5931cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5932cf5a6209SStefano Zampini     }
5933cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
593408122e43SStefano Zampini   } else {
593508122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5936984c4197SStefano Zampini 
593708122e43SStefano Zampini     total_counts = 0;
593808122e43SStefano Zampini     n_vertices = 0;
5939d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5940d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
594108122e43SStefano Zampini     }
594208122e43SStefano Zampini     max_constraints = 0;
59439162d606SStefano Zampini     total_counts_cc = 0;
594408122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
594508122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
59469162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
594708122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
594808122e43SStefano Zampini     }
59499162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
59509162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
59519162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
59529162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
595374d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
59549162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
59559162d606SStefano Zampini     total_counts_cc = 0;
59569162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
59579162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
59589162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
595908122e43SStefano Zampini       }
596008122e43SStefano Zampini     }
59619162d606SStefano Zampini #if 0
59629162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
59639162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
59649162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
59659162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
59669162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
59679162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
59689162d606SStefano Zampini       }
59699162d606SStefano Zampini       printf("\n");
59709162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
59719162d606SStefano Zampini     }
59721b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
59738bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
59741b968477SStefano Zampini     }
59751b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
59768bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] sub %d, edge %d, n %d\n",PetscGlobalRank,i,(PetscBool)PetscBTLookup(sub_schurs->is_edge,i),pcbddc->adaptive_constraints_n[i+n_vertices]);
59771b968477SStefano Zampini     }
597808122e43SStefano Zampini #endif
597908122e43SStefano Zampini 
59808bec7fa6SStefano Zampini     max_size_of_constraint = 0;
59819162d606SStefano 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]);
59829162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
598308122e43SStefano Zampini     /* Change of basis */
5984b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
598508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
598608122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
598708122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5988b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
598908122e43SStefano Zampini         }
599008122e43SStefano Zampini       }
599108122e43SStefano Zampini     }
599208122e43SStefano Zampini   }
5993984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
59944f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
599508122e43SStefano Zampini 
59969162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
59979162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
5998eee23b56SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
5999674ae819SStefano Zampini 
6000674ae819SStefano Zampini   /* Create constraint matrix */
6001674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
600216f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
6003984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
6004984c4197SStefano Zampini 
6005984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6006a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
6007a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
600874d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
6009984c4197SStefano Zampini   total_primal_vertices=0;
6010b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
60119162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
60129162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
601372b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
60149162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6015b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
601664efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
60179162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
60189162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6019a717540cSStefano Zampini       }
6020b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
602191af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6022a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6023a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6024a717540cSStefano Zampini       }
6025fa434743SStefano Zampini     } else {
6026b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6027fa434743SStefano Zampini     }
6028a717540cSStefano Zampini   }
6029b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6030b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6031674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
603270022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
60334f1b2e48SStefano 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);
60340e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
60350e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6036984c4197SStefano Zampini 
6037984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
603874d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
6039785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
6040984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
604174d5cdf7SStefano Zampini 
6042984c4197SStefano Zampini   j = total_primal_vertices;
604374d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6044b3d85658SStefano Zampini   cum = total_primal_vertices;
60459162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
60464641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6047b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6048b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6049b3d85658SStefano Zampini       cum++;
60509162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
605174d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
605274d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
605374d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
605474d5cdf7SStefano Zampini       }
60559162d606SStefano Zampini       j += constraints_n[i];
6056674ae819SStefano Zampini     }
6057674ae819SStefano Zampini   }
6058674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
6059674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
6060088faed8SStefano Zampini 
6061674ae819SStefano Zampini   /* set values in constraint matrix */
6062984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
60630e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6064674ae819SStefano Zampini   }
6065984c4197SStefano Zampini   total_counts = total_primal_vertices;
60669162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
60674641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
60689162d606SStefano Zampini       PetscInt *cols;
60699162d606SStefano Zampini 
60709162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
60719162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
60729162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
60739162d606SStefano Zampini         PetscInt    row = total_counts+k;
60749162d606SStefano Zampini         PetscScalar *vals;
60759162d606SStefano Zampini 
60769162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
60779162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
60789162d606SStefano Zampini       }
60799162d606SStefano Zampini       total_counts += constraints_n[i];
6080674ae819SStefano Zampini     }
6081674ae819SStefano Zampini   }
6082674ae819SStefano Zampini   /* assembling */
6083674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6084674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6085088faed8SStefano Zampini 
6086984c4197SStefano Zampini   /*
60876a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6088984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
6089f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
6090984c4197SStefano Zampini   */
6091674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6092674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6093026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6094984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6095984c4197SStefano Zampini     /* working stuff for GEQRF */
609681d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
6097984c4197SStefano Zampini     PetscBLASInt lqr_work;
6098984c4197SStefano Zampini     /* working stuff for UNGQR */
6099984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
6100984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6101984c4197SStefano Zampini     /* working stuff for TRTRS */
6102984c4197SStefano Zampini     PetscScalar  *trs_rhs;
61033f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6104984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6105984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6106984c4197SStefano Zampini     PetscScalar  *start_vals;
6107984c4197SStefano Zampini     /* working stuff for values insertion */
61084641a718SStefano Zampini     PetscBT      is_primal;
610964efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6110906d46d4SStefano Zampini     /* matrix sizes */
6111906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6112906d46d4SStefano Zampini     /* temporary change of basis */
6113906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6114cf5a6209SStefano Zampini     /* extra space for debugging */
6115cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
6116984c4197SStefano Zampini 
6117906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
6118906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
611916f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
6120bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
6121906d46d4SStefano Zampini     /* nonzeros for local mat */
6122bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
61231dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6124bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
61251dd7afcfSStefano Zampini     } else {
61261dd7afcfSStefano Zampini       const PetscInt *ii;
61271dd7afcfSStefano Zampini       PetscInt       n;
61281dd7afcfSStefano Zampini       PetscBool      flg_row;
61291dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
61301dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
61311dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
61321dd7afcfSStefano Zampini     }
61339162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6134a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
61359162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6136a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
61379162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6138a717540cSStefano Zampini         } else {
61399162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
61409162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6141a717540cSStefano Zampini         }
6142a717540cSStefano Zampini       }
6143a717540cSStefano Zampini     }
6144906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
6145bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
61461dd7afcfSStefano Zampini     /* Set interior change in the matrix */
61471dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6148bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
6149906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
6150a717540cSStefano Zampini       }
61511dd7afcfSStefano Zampini     } else {
61521dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
61531dd7afcfSStefano Zampini       PetscScalar    *aa;
61541dd7afcfSStefano Zampini       PetscInt       n;
61551dd7afcfSStefano Zampini       PetscBool      flg_row;
61561dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
61571dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
61581dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
61591dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
61601dd7afcfSStefano Zampini       }
61611dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
61621dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
61631dd7afcfSStefano Zampini     }
6164a717540cSStefano Zampini 
6165a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
6166a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6167a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6168a717540cSStefano Zampini     }
6169a717540cSStefano Zampini 
6170a717540cSStefano Zampini 
6171a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6172a717540cSStefano Zampini     /*
6173a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6174a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6175a717540cSStefano Zampini 
6176a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6177a717540cSStefano Zampini 
6178a6b551f4SStefano 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)
6179a6b551f4SStefano Zampini 
6180a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6181a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6182a717540cSStefano Zampini             |              ...                        |
6183a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6184a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6185a717540cSStefano Zampini 
6186a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6187a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6188a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6189a6b551f4SStefano Zampini 
6190a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6191a717540cSStefano Zampini     */
6192a717540cSStefano Zampini     if (qr_needed) {
6193984c4197SStefano Zampini       /* space to store Q */
6194854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
61954e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
61964e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
6197984c4197SStefano Zampini       /* first we issue queries for optimal work */
61983f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
61993f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
62003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6201984c4197SStefano Zampini       lqr_work = -1;
62023f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
6203984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
6204984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
6205785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
6206984c4197SStefano Zampini       lgqr_work = -1;
62073f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
62083f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
62093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
62103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62113f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6212c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
6213c964aadfSJose E. Roman       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
6214984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
6215785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
6216984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
6217785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
6218a717540cSStefano Zampini       /* allocating workspace for check */
6219a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
6220cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
6221a717540cSStefano Zampini       }
6222a717540cSStefano Zampini     }
6223984c4197SStefano Zampini     /* array to store whether a node is primal or not */
62244641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
6225473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
62260e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
6227eee23b56SStefano Zampini     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
622839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
622939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
623039e2fb2aSStefano Zampini     }
623139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
6232984c4197SStefano Zampini 
6233a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
62349162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
62359162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
62364641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6237984c4197SStefano Zampini         /* get constraint info */
62389162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6239984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6240984c4197SStefano Zampini 
6241984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
62429162d606SStefano 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);
6243674ae819SStefano Zampini         }
6244984c4197SStefano Zampini 
6245fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6246a717540cSStefano Zampini 
6247a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6248a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
62499162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6250a717540cSStefano Zampini           }
6251984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
62529162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6253984c4197SStefano Zampini 
6254984c4197SStefano Zampini           /* compute QR decomposition of constraints */
62553f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62563f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62573f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6258674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62593f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
6260984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
6261674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6262984c4197SStefano Zampini 
6263984c4197SStefano Zampini           /* explictly compute R^-T */
6264984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
6265984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
62663f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62673f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
62683f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62693f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
6270984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62713f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
6272984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
6273984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6274984c4197SStefano Zampini 
6275a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
62763f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62773f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
62783f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
62793f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6280984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6281c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
6282c964aadfSJose E. Roman           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
6283984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
6284984c4197SStefano Zampini 
6285984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6286984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6287984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
62883f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
62893f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
62903f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
62913f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
62923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
62933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
6294984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
62959162d606SStefano 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));
6296984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
62979162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
6298984c4197SStefano Zampini 
6299984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
63009162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6301984c4197SStefano Zampini           /* insert cols for primal dofs */
6302984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6303984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
63049162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6305906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6306984c4197SStefano Zampini           }
6307984c4197SStefano Zampini           /* insert cols for dual dofs */
6308984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
63099162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6310984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
63119162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6312906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
6313984c4197SStefano Zampini               j++;
6314674ae819SStefano Zampini             }
6315674ae819SStefano Zampini           }
6316984c4197SStefano Zampini 
6317984c4197SStefano Zampini           /* check change of basis */
6318984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6319984c4197SStefano Zampini             PetscInt   ii,jj;
6320984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
6321c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
6322c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
6323c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
6324c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
6325c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
6326c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
6327984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
6328cf5a6209SStefano 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));
6329984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
6330984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6331984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6332cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6333c068d9bbSLisandro 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;
6334674ae819SStefano Zampini               }
6335674ae819SStefano Zampini             }
6336984c4197SStefano Zampini             if (!valid_qr) {
633722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
6338984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6339984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6340cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
6341cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6342674ae819SStefano Zampini                   }
6343c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
6344cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
6345984c4197SStefano Zampini                   }
6346984c4197SStefano Zampini                 }
6347984c4197SStefano Zampini               }
6348674ae819SStefano Zampini             } else {
634922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
6350674ae819SStefano Zampini             }
6351674ae819SStefano Zampini           }
6352a717540cSStefano Zampini         } else { /* simple transformation block */
6353a717540cSStefano Zampini           PetscInt    row,col;
6354a6b551f4SStefano Zampini           PetscScalar val,norm;
6355a6b551f4SStefano Zampini 
6356a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
63579162d606SStefano 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));
6358a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
63599162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
63609162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6361bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
63629162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6363906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
63649162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6365a717540cSStefano Zampini             } else {
6366a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
63679162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6368a717540cSStefano Zampini                 if (row != col) {
63699162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6370a717540cSStefano Zampini                 } else {
63719162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6372a717540cSStefano Zampini                 }
6373906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6374a717540cSStefano Zampini               }
6375a717540cSStefano Zampini             }
6376a717540cSStefano Zampini           }
637798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
637822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6379a717540cSStefano Zampini           }
6380674ae819SStefano Zampini         }
6381984c4197SStefano Zampini       } else {
6382984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
63839162d606SStefano 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);
6384674ae819SStefano Zampini         }
6385674ae819SStefano Zampini       }
6386674ae819SStefano Zampini     }
6387a717540cSStefano Zampini 
6388a717540cSStefano Zampini     /* free workspace */
6389a717540cSStefano Zampini     if (qr_needed) {
6390984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6391cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6392984c4197SStefano Zampini       }
6393984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6394984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6395984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6396984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6397984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6398674ae819SStefano Zampini     }
6399a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6400906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6401906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6402906d46d4SStefano Zampini 
6403906d46d4SStefano Zampini     /* assembling of global change of variable */
640488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6405bbb9e6c6SStefano Zampini       Mat      tmat;
640616f15bc4SStefano Zampini       PetscInt bs;
640716f15bc4SStefano Zampini 
6408906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6409906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6410bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6411bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6412bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6413bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
641416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
641516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6416906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6417bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6418bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6419bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6420bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6421bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6422e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6423e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6424bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6425bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
642688c03ad3SStefano Zampini 
6427906d46d4SStefano Zampini       /* check */
6428906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6429906d46d4SStefano Zampini         PetscReal error;
6430906d46d4SStefano Zampini         Vec       x,x_change;
6431906d46d4SStefano Zampini 
6432906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6433906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6434906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6435906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6436e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6437e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6438bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6439e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6440e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6441906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6442906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6443906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6444637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6445637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6446637e8532SStefano Zampini         }
6447906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6448906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6449906d46d4SStefano Zampini       }
6450b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6451b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6452b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6453bf3a8328SStefano Zampini 
645413903a91SSatish 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");
6455b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6456ac632422SStefano Zampini           Mat                    S_new,tmat;
6457bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6458bbb9e6c6SStefano Zampini 
6459bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
64607dae84e0SHong Zhang           ierr = MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6461bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6462bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6463bf3a8328SStefano Zampini             IS                     is_V;
6464b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6465b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6466b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6467b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6468b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6469bf3a8328SStefano Zampini           }
6470bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6471ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6472b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6473ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6474bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6475bf3a8328SStefano Zampini             const PetscScalar *array;
6476bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6477bf3a8328SStefano Zampini             PetscInt          i,n_V;
6478bf3a8328SStefano Zampini 
6479b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6480b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6481b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6482b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6483b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6484b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6485b087196eSStefano Zampini               PetscScalar val;
6486b087196eSStefano Zampini               PetscInt    idx;
6487b087196eSStefano Zampini 
6488b087196eSStefano Zampini               idx = idxs_V[i];
6489b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6490b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6491b087196eSStefano Zampini             }
6492b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6493b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6494bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6495bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6496bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6497bf3a8328SStefano Zampini           }
6498ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6499ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6500ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6501ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6502b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6503ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6504bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6505b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6506bf3a8328SStefano Zampini             }
6507ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6508ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6509ac632422SStefano Zampini           }
6510b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
651188c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6512b96c3477SStefano Zampini         }
6513c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6514b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6515c9db6a07SStefano Zampini           PetscInt i;
6516c9db6a07SStefano Zampini 
6517c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6518c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6519c9db6a07SStefano Zampini           }
6520c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6521c9db6a07SStefano Zampini         }
6522b96c3477SStefano Zampini       }
652316909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
652416909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
652516909a7fSStefano Zampini       } else {
6526906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
652716909a7fSStefano Zampini       }
65281dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
652927b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
653072b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
653172b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
653272b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
653372b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
653472b8c272SStefano Zampini     }
65351dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
653627b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6537b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6538b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6539906d46d4SStefano Zampini     } else {
65401dd7afcfSStefano Zampini       Mat benign_global = NULL;
654127b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
65421dd7afcfSStefano Zampini         Mat tmat;
65431dd7afcfSStefano Zampini 
65441dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
65451dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
65461dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
65471dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
65481dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
65491dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
65501dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
65511dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
65521dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
65531dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
65541dd7afcfSStefano Zampini           Mat M;
65551dd7afcfSStefano Zampini 
65561dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
65571dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
65581dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
65591dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6560906d46d4SStefano Zampini         } else {
65611dd7afcfSStefano Zampini           Mat         eye;
65621dd7afcfSStefano Zampini           PetscScalar *array;
65631dd7afcfSStefano Zampini 
65641dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
65651dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
65661dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
65671dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6568906d46d4SStefano Zampini           }
65691dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
65701dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65711dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65721dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
65731dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
65741dd7afcfSStefano Zampini         }
65751dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
65761dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
65771dd7afcfSStefano Zampini       }
65781dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
65791dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
65801dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
658127b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
65821dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
65831dd7afcfSStefano Zampini       }
65841dd7afcfSStefano Zampini     }
658516909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
658616909a7fSStefano Zampini       IS             is_global;
658716909a7fSStefano Zampini       const PetscInt *gidxs;
658816909a7fSStefano Zampini 
658916909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
659016909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
659116909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
65927dae84e0SHong Zhang       ierr = MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
659316909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
659416909a7fSStefano Zampini     }
65951dd7afcfSStefano Zampini   }
65961dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
65971dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6598b9b85e73SStefano Zampini   }
6599a717540cSStefano Zampini 
660072b8c272SStefano Zampini   if (!pcbddc->fake_change) {
66014f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
66024f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66034f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
66044f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6605019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6606019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6607019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6608019a44ceSStefano Zampini     }
6609019a44ceSStefano Zampini 
6610019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6611727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6612727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
66139f47a83aSStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6614c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
66150e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
66169f47a83aSStefano Zampini         ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
6617727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6618727cdba6SStefano Zampini       }
66190e6343abSStefano Zampini     }
6620727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6621b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
662272b8c272SStefano Zampini   }
662372b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6624727cdba6SStefano Zampini 
6625a717540cSStefano Zampini   /* flush dbg viewer */
6626b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6627b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6628b8ffe317SStefano Zampini   }
6629a717540cSStefano Zampini 
6630e310c8b4SStefano Zampini   /* free workspace */
6631a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
66324641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
663308122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
66349162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
66359162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
663608122e43SStefano Zampini   } else {
66379162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
66389162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
66399162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
664008122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
664108122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
66429162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
66439162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
664408122e43SStefano Zampini   }
6645674ae819SStefano Zampini   PetscFunctionReturn(0);
6646674ae819SStefano Zampini }
6647674ae819SStefano Zampini 
6648674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6649674ae819SStefano Zampini {
665071582508SStefano Zampini   ISLocalToGlobalMapping map;
6651674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6652674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
665366da6bd7Sstefano_zampini   PetscInt               i,N;
665466da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
665566da6bd7Sstefano_zampini   PetscErrorCode         ierr;
6656674ae819SStefano Zampini 
6657674ae819SStefano Zampini   PetscFunctionBegin;
66588af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6659b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
66608e61c736SStefano Zampini     /* Reset previously computed graph */
66618e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6662674ae819SStefano Zampini     /* Init local Graph struct */
66637fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
666471582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6665be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6666674ae819SStefano Zampini 
66677a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
66687a0e7b2cSstefano_zampini       ierr = PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
66697a0e7b2cSstefano_zampini     }
6670575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
66719a962809SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %d, expected %d\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
66729577ea80SStefano Zampini 
6673674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
667466da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
66754d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
66764d379d7bSStefano Zampini       PetscInt  nvtxs;
6677e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6678674ae819SStefano Zampini 
66792fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
66802fffb893SStefano Zampini       if (flg_row) {
66814d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6682b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
66832fffb893SStefano Zampini       }
66842fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
668566da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
6686674ae819SStefano Zampini     }
66879b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
66889b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6689674ae819SStefano Zampini     }
6690674ae819SStefano Zampini 
6691674ae819SStefano Zampini     /* Setup of Graph */
66924b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
669314f95afaSStefano 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);
6694674ae819SStefano Zampini 
66954f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
66964f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
66974f1b2e48SStefano Zampini       PetscInt *local_subs;
66984f1b2e48SStefano Zampini 
66994f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
67004f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
67014f1b2e48SStefano Zampini         const PetscInt *idxs;
67024f1b2e48SStefano Zampini         PetscInt       nl,j;
67034f1b2e48SStefano Zampini 
67044f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
67054f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
670671582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
67074f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
67084f1b2e48SStefano Zampini       }
67094f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
67104f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
67114f1b2e48SStefano Zampini     }
67128af8fcf9SStefano Zampini   }
67134f1b2e48SStefano Zampini 
6714cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6715674ae819SStefano Zampini     /* Graph's connected components analysis */
6716674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
671771582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
67188af8fcf9SStefano Zampini   }
671966da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
6720674ae819SStefano Zampini   PetscFunctionReturn(0);
6721674ae819SStefano Zampini }
6722674ae819SStefano Zampini 
67239a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
67249a7d3425SStefano Zampini {
67259a7d3425SStefano Zampini   PetscInt       i,j;
67269a7d3425SStefano Zampini   PetscScalar    *alphas;
67279a7d3425SStefano Zampini   PetscErrorCode ierr;
67289a7d3425SStefano Zampini 
67299a7d3425SStefano Zampini   PetscFunctionBegin;
6730785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
67319a7d3425SStefano Zampini   for (i=0;i<n;i++) {
67329a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6733669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6734669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6735669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
67369a7d3425SStefano Zampini   }
67379a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
67389a7d3425SStefano Zampini   PetscFunctionReturn(0);
67399a7d3425SStefano Zampini }
67409a7d3425SStefano Zampini 
6741bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6742e7931f94SStefano Zampini {
674357de7509SStefano Zampini   Mat            A;
6744e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6745e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
674652e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
674752e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6748bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
674957de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
675027b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
675127b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
675227b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
675327b6a85dSStefano Zampini   MPI_Comm       subcomm;
675452e5ac9dSStefano Zampini   PetscErrorCode ierr;
6755a57a6d2fSStefano Zampini 
6756e7931f94SStefano Zampini   PetscFunctionBegin;
675757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
675857de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
6759fbfcfee5SBarry 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);
676057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
676157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
676257de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
676357de7509SStefano Zampini 
676457de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
676557de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
676657de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
676757de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
676857de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6769bb360cb4SStefano Zampini   im_active = !!n;
677057de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
677157de7509SStefano Zampini   void_procs = size - active_procs;
677257de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
677357de7509SStefano Zampini   if (void_procs) {
677457de7509SStefano Zampini     PetscInt ncand;
677557de7509SStefano Zampini 
677657de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
677757de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
677857de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
677957de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
678057de7509SStefano Zampini       if (!procs_candidates[i]) {
678157de7509SStefano Zampini         procs_candidates[ncand++] = i;
678257de7509SStefano Zampini       }
678357de7509SStefano Zampini     }
678457de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
678557de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
678657de7509SStefano Zampini   }
678757de7509SStefano Zampini 
6788bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
678914f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
6790bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
6791bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
679214f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
679314f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
679414f0bfb9SStefano Zampini     else dest = rank;
679557de7509SStefano Zampini     if (im_active) {
679657de7509SStefano Zampini       issize = 1;
679757de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
679814f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
679957de7509SStefano Zampini       } else {
680014f0bfb9SStefano Zampini         isidx = dest;
680157de7509SStefano Zampini       }
680257de7509SStefano Zampini     } else {
680357de7509SStefano Zampini       issize = 0;
680457de7509SStefano Zampini       isidx = -1;
680557de7509SStefano Zampini     }
6806bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
680757de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6808daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
680957de7509SStefano Zampini     PetscFunctionReturn(0);
681057de7509SStefano Zampini   }
6811c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6812c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
681327b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6814e7931f94SStefano Zampini 
6815e7931f94SStefano Zampini   /* Get info on mapping */
68163bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6817e7931f94SStefano Zampini 
6818e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6819785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6820e7931f94SStefano Zampini   xadj[0] = 0;
6821e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6822785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6823785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
6824bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
682527b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
682627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
682727b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6828e7931f94SStefano Zampini 
682927b6a85dSStefano Zampini   xadj_count = 0;
68302b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
683127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
683227b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6833d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6834d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6835d023bfaeSStefano Zampini         xadj_count++;
683627b6a85dSStefano Zampini         break;
683727b6a85dSStefano Zampini       }
6838e7931f94SStefano Zampini     }
6839e7931f94SStefano Zampini   }
6840d023bfaeSStefano Zampini   xadj[1] = xadj_count;
684127b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
68423bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6843e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6844e7931f94SStefano Zampini 
68453837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6846e7931f94SStefano Zampini 
684727b6a85dSStefano Zampini   /* Restrict work on active processes only */
684827b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
684927b6a85dSStefano Zampini   if (void_procs) {
685027b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
685127b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
685227b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
685327b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
685427b6a85dSStefano Zampini   } else {
685527b6a85dSStefano Zampini     psubcomm = NULL;
685627b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
685727b6a85dSStefano Zampini   }
685827b6a85dSStefano Zampini 
685927b6a85dSStefano Zampini   v_wgt = NULL;
686027b6a85dSStefano Zampini   if (!color) {
6861e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6862e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6863e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6864c8587f34SStefano Zampini   } else {
686552e5ac9dSStefano Zampini     Mat             subdomain_adj;
686652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
686752e5ac9dSStefano Zampini     MatPartitioning partitioner;
686827b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
686952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
687057de7509SStefano Zampini     PetscMPIInt     size;
6871b0c7d250SStefano Zampini     PetscBool       aggregate;
6872b0c7d250SStefano Zampini 
687327b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
687427b6a85dSStefano Zampini     if (void_procs) {
687527b6a85dSStefano Zampini       PetscInt prank = rank;
6876785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
687727b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6878e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6879e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6880c8587f34SStefano Zampini       }
6881e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
688227b6a85dSStefano Zampini     } else {
688327b6a85dSStefano Zampini       oldranks = NULL;
688427b6a85dSStefano Zampini     }
6885b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
688627b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6887b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6888b0c7d250SStefano Zampini       PetscMPIInt nrank;
6889b0c7d250SStefano Zampini       PetscScalar *vals;
6890b0c7d250SStefano Zampini 
689127b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6892b0c7d250SStefano Zampini       lrows = 0;
6893b0c7d250SStefano Zampini       if (nrank<redprocs) {
6894b0c7d250SStefano Zampini         lrows = size/redprocs;
6895b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6896b0c7d250SStefano Zampini       }
689727b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6898b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6899b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6900b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6901b0c7d250SStefano Zampini       row = nrank;
6902b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6903b0c7d250SStefano Zampini       cols = adjncy;
6904b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6905b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6906b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6907b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6908b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
690952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
691052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
691152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6912b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
691327b6a85dSStefano Zampini       if (use_vwgt) {
691427b6a85dSStefano Zampini         Vec               v;
691527b6a85dSStefano Zampini         const PetscScalar *array;
691627b6a85dSStefano Zampini         PetscInt          nl;
691727b6a85dSStefano Zampini 
691827b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
6919bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
692027b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
692127b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
692227b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
692327b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
692427b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
692522db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
692627b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
692727b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
692827b6a85dSStefano Zampini       }
6929b0c7d250SStefano Zampini     } else {
693027b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
693127b6a85dSStefano Zampini       if (use_vwgt) {
693227b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
6933bb360cb4SStefano Zampini         v_wgt[0] = n;
693427b6a85dSStefano Zampini       }
6935b0c7d250SStefano Zampini     }
693622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6937e7931f94SStefano Zampini 
6938e7931f94SStefano Zampini     /* Partition */
693927b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6940e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
694127b6a85dSStefano Zampini     if (v_wgt) {
6942e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6943c8587f34SStefano Zampini     }
694457de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
694557de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6946e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6947e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
694822b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6949e7931f94SStefano Zampini 
695052e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
69516583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
695252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
695352e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
695457de7509SStefano Zampini     if (!aggregate) {
695557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
695627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
695727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
695827b6a85dSStefano Zampini #endif
695957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
696027b6a85dSStefano Zampini       } else if (oldranks) {
6961b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
696227b6a85dSStefano Zampini       } else {
696327b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
696457de7509SStefano Zampini       }
696528143c3dSStefano Zampini     } else {
69667fb8a5e4SKarl Rupp       PetscInt    idx = 0;
6967b0c7d250SStefano Zampini       PetscMPIInt tag;
6968b0c7d250SStefano Zampini       MPI_Request *reqs;
6969b0c7d250SStefano Zampini 
6970b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6971b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6972b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
697327b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
697428143c3dSStefano Zampini       }
69757fb8a5e4SKarl Rupp       ierr = MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6976b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6977b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
697857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
697927b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
698027b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
698127b6a85dSStefano Zampini #endif
69827fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
698327b6a85dSStefano Zampini       } else if (oldranks) {
69847fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
698527b6a85dSStefano Zampini       } else {
69867fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
6987e7931f94SStefano Zampini       }
698857de7509SStefano Zampini     }
698952e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6990e7931f94SStefano Zampini     /* clean up */
6991e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
699252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6993e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6994e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6995e7931f94SStefano Zampini   }
699627b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
699757de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6998e7931f94SStefano Zampini 
6999e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7000e7931f94SStefano Zampini   i = 1;
700127b6a85dSStefano Zampini   if (!color) i=0;
700257de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
7003e7931f94SStefano Zampini   PetscFunctionReturn(0);
7004e7931f94SStefano Zampini }
7005e7931f94SStefano Zampini 
7006e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7007e7931f94SStefano Zampini 
70081e0482f5SStefano 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[])
7009e7931f94SStefano Zampini {
701070cf5478SStefano Zampini   Mat                    local_mat;
7011e7931f94SStefano Zampini   IS                     is_sends_internal;
70129d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
70131ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
70149d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7015e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7016e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7017e7931f94SStefano Zampini   const PetscInt*        is_indices;
7018e7931f94SStefano Zampini   MatType                new_local_type;
7019e7931f94SStefano Zampini   /* buffers */
7020e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
702128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
70229d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
7023e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
70241ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7025e7931f94SStefano Zampini   /* MPI */
702628143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
702728143c3dSStefano Zampini   PetscSubcomm           subcomm;
7028e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
702928143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
703028143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
70311ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
70321ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
70331ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7034e7931f94SStefano Zampini   PetscErrorCode         ierr;
7035e7931f94SStefano Zampini 
7036e7931f94SStefano Zampini   PetscFunctionBegin;
703757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7038e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
7039fbfcfee5SBarry 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);
704057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
704157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
704257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
704357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
704457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
70451ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
70461ae86dd6SStefano Zampini   if (nvecs) {
70471ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
70481ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
70491ae86dd6SStefano Zampini   }
705057de7509SStefano Zampini   /* further checks */
7051e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7052e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7053e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
7054e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
7055e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
705657de7509SStefano Zampini   if (reuse && *mat_n) {
705770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
705857de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
705970cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
706028143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
706170cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
706270cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
706370cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
706470cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
706570cf5478SStefano Zampini   }
7066e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
7067e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
706857de7509SStefano Zampini 
7069e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7070e7931f94SStefano Zampini   if (!is_sends) {
707128143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
7072bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
7073c8587f34SStefano Zampini   } else {
7074e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
7075e7931f94SStefano Zampini     is_sends_internal = is_sends;
7076c8587f34SStefano Zampini   }
7077e7931f94SStefano Zampini 
7078e7931f94SStefano Zampini   /* get comm */
7079a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
7080e7931f94SStefano Zampini 
7081e7931f94SStefano Zampini   /* compute number of sends */
7082e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
7083e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
7084e7931f94SStefano Zampini 
7085e7931f94SStefano Zampini   /* compute number of receives */
7086e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
7087785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
7088e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
7089e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7090e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
7091e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
7092e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
7093e7931f94SStefano Zampini 
709428143c3dSStefano Zampini   /* restrict comm if requested */
709528143c3dSStefano Zampini   subcomm = 0;
709628143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
709728143c3dSStefano Zampini   if (restrict_comm) {
7098779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7099779c1cceSStefano Zampini 
710028143c3dSStefano Zampini     color = 0;
710153a05cb3SStefano Zampini     if (restrict_full) {
710253a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
710353a05cb3SStefano Zampini     } else {
710453a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
710553a05cb3SStefano Zampini     }
7106b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
710728143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
710828143c3dSStefano Zampini     /* check if reuse has been requested */
710957de7509SStefano Zampini     if (reuse) {
711028143c3dSStefano Zampini       if (*mat_n) {
711128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
711228143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
711328143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
711428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
711528143c3dSStefano Zampini       } else {
711628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
711728143c3dSStefano Zampini       }
711828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7119779c1cceSStefano Zampini       PetscMPIInt rank;
7120779c1cceSStefano Zampini 
7121779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
712228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
712328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
712428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
7125306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
712628143c3dSStefano Zampini     }
712728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
712828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
712928143c3dSStefano Zampini   } else {
713028143c3dSStefano Zampini     comm_n = comm;
713128143c3dSStefano Zampini   }
713228143c3dSStefano Zampini 
7133e7931f94SStefano Zampini   /* prepare send/receive buffers */
7134785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
7135e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
7136785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
7137e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
713828143c3dSStefano Zampini   if (nis) {
7139854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
714028143c3dSStefano Zampini   }
7141e7931f94SStefano Zampini 
714228143c3dSStefano Zampini   /* Get data from local matrices */
71436c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7144e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7145e7931f94SStefano Zampini     /*
7146e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7147e7931f94SStefano Zampini        send_buffer_idxs should contain:
7148e7931f94SStefano Zampini        - MatType_PRIVATE type
7149e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7150e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7151e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7152e7931f94SStefano Zampini     */
71536c4ed002SBarry Smith   else {
7154e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
71553bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
7156854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
7157e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7158e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
71593bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7160e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
71613bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
7162e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
7163e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7164e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7165e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7166c8587f34SStefano Zampini     }
7167c8587f34SStefano Zampini   }
7168e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
716928143c3dSStefano Zampini   /* additional is (if any) */
717028143c3dSStefano Zampini   if (nis) {
717128143c3dSStefano Zampini     PetscMPIInt psum;
717228143c3dSStefano Zampini     PetscInt j;
717328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
717428143c3dSStefano Zampini       PetscInt plen;
717528143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
717628143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
717728143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
717828143c3dSStefano Zampini     }
7179854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
718028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
718128143c3dSStefano Zampini       PetscInt plen;
718228143c3dSStefano Zampini       const PetscInt *is_array_idxs;
718328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
718428143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
718528143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
718628143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
718728143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
718828143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
718928143c3dSStefano Zampini     }
719028143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
719128143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
719228143c3dSStefano Zampini     }
719328143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
719428143c3dSStefano Zampini   }
71953b3b1effSJed Brown   ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
719628143c3dSStefano Zampini 
7197e7931f94SStefano Zampini   buf_size_idxs = 0;
7198e7931f94SStefano Zampini   buf_size_vals = 0;
719928143c3dSStefano Zampini   buf_size_idxs_is = 0;
72001ae86dd6SStefano Zampini   buf_size_vecs = 0;
7201e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7202e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7203e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
720428143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
72051ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7206e7931f94SStefano Zampini   }
7207785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
7208785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
720995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
72101ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
7211e7931f94SStefano Zampini 
7212e7931f94SStefano Zampini   /* get new tags for clean communications */
7213e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
7214e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
721528143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
72161ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
7217e7931f94SStefano Zampini 
7218e7931f94SStefano Zampini   /* allocate for requests */
7219785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
7220785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
722195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
72221ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
7223785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
7224785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
722595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
72261ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
7227e7931f94SStefano Zampini 
7228e7931f94SStefano Zampini   /* communications */
7229e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7230e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
723128143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
72321ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7233e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7234e7931f94SStefano Zampini     source_dest = onodes[i];
7235e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
7236e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
7237e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7238e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
723928143c3dSStefano Zampini     if (nis) {
724057de7509SStefano Zampini       source_dest = onodes_is[i];
724128143c3dSStefano Zampini       ierr = MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]);CHKERRQ(ierr);
724228143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
724328143c3dSStefano Zampini     }
72441ae86dd6SStefano Zampini     if (nvecs) {
72451ae86dd6SStefano Zampini       source_dest = onodes[i];
72461ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
72471ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
72481ae86dd6SStefano Zampini     }
7249e7931f94SStefano Zampini   }
7250e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
7251e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
7252e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
7253e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
725428143c3dSStefano Zampini     if (nis) {
725528143c3dSStefano Zampini       ierr = MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i]);CHKERRQ(ierr);
725628143c3dSStefano Zampini     }
72571ae86dd6SStefano Zampini     if (nvecs) {
72581ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
72591ae86dd6SStefano Zampini       ierr = MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]);CHKERRQ(ierr);
72601ae86dd6SStefano Zampini     }
7261e7931f94SStefano Zampini   }
7262e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
7263e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
7264e7931f94SStefano Zampini 
7265e7931f94SStefano Zampini   /* assemble new l2g map */
7266e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7267e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
72689d30be91SStefano Zampini   new_local_rows = 0;
7269e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
72709d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7271e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7272e7931f94SStefano Zampini   }
72739d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
7274e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
72759d30be91SStefano Zampini   new_local_rows = 0;
7276e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
72779d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
72789d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7279e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7280e7931f94SStefano Zampini   }
72819d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
72829d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
7283e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
7284e7931f94SStefano Zampini 
7285e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7286e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7287e7931f94SStefano 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) */
7288e7931f94SStefano Zampini   if (n_recvs) {
728928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7290e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7291e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7292e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7293e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7294e7931f94SStefano Zampini         break;
7295e7931f94SStefano Zampini       }
7296e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7297e7931f94SStefano Zampini     }
7298e7931f94SStefano Zampini     switch (new_local_type_private) {
729928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7300e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7301e7931f94SStefano Zampini         bs = 1;
7302e7931f94SStefano Zampini         break;
7303e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7304e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7305e7931f94SStefano Zampini         bs = 1;
7306e7931f94SStefano Zampini         break;
7307e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7308e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7309e7931f94SStefano Zampini         break;
7310e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7311e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7312e7931f94SStefano Zampini         break;
7313e7931f94SStefano Zampini       default:
7314fbfcfee5SBarry Smith         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7315e7931f94SStefano Zampini         break;
7316e7931f94SStefano Zampini     }
7317ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7318ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
731928143c3dSStefano Zampini     bs = 1;
7320e7931f94SStefano Zampini   }
7321e7931f94SStefano Zampini 
732270cf5478SStefano Zampini   /* create MATIS object if needed */
732357de7509SStefano Zampini   if (!reuse) {
7324e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
7325e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
732670cf5478SStefano Zampini   } else {
732770cf5478SStefano Zampini     /* it also destroys the local matrices */
732857de7509SStefano Zampini     if (*mat_n) {
732970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
733057de7509SStefano Zampini     } else { /* this is a fake object */
733157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
733257de7509SStefano Zampini     }
733370cf5478SStefano Zampini   }
733470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
7335e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
73369d30be91SStefano Zampini 
73379d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
73389d30be91SStefano Zampini 
73399d30be91SStefano Zampini   /* Global to local map of received indices */
73409d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
73419d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
73429d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
73439d30be91SStefano Zampini 
73449d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
73459d30be91SStefano Zampini   buf_size_idxs = 0;
73469d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
73479d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
73489d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
73499d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
73509d30be91SStefano Zampini   }
73519d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
73529d30be91SStefano Zampini 
73539d30be91SStefano Zampini   /* set preallocation */
73549d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
73559d30be91SStefano Zampini   if (!newisdense) {
73569d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
73579d30be91SStefano Zampini 
73589d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
73599d30be91SStefano Zampini     if (n_recvs) {
73609d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
73619d30be91SStefano Zampini     }
73629d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
73639d30be91SStefano Zampini       PetscInt j;
73649d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
73659d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
73669d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
73679d30be91SStefano Zampini         }
73689d30be91SStefano Zampini       } else {
73699d30be91SStefano Zampini         /* TODO */
73709d30be91SStefano Zampini       }
73719d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
73729d30be91SStefano Zampini     }
73739d30be91SStefano Zampini     if (new_local_nnz) {
73749d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
73759d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
73769d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
73779d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
73789d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
73799d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
73809d30be91SStefano Zampini     } else {
73819d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
73829d30be91SStefano Zampini     }
73839d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
73849d30be91SStefano Zampini   } else {
73859d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
73869d30be91SStefano Zampini   }
7387e7931f94SStefano Zampini 
7388e7931f94SStefano Zampini   /* set values */
7389e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
73909d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7391e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7392e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7393e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
73949d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7395e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7396e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7397e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
739828143c3dSStefano Zampini     } else {
739928143c3dSStefano Zampini       /* TODO */
7400e7931f94SStefano Zampini     }
7401e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7402e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7403e7931f94SStefano Zampini   }
7404e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7405e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
74063b3b1effSJed Brown   ierr = MatISRestoreLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
740770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
740870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
74099d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7410e7931f94SStefano Zampini 
7411dfd14d43SStefano Zampini #if 0
741228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7413e7931f94SStefano Zampini     Vec       lvec,rvec;
7414e7931f94SStefano Zampini     PetscReal infty_error;
7415e7931f94SStefano Zampini 
74162a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7417e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7418e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7419e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
742070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7421e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7422e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7423e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7424e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7425e7931f94SStefano Zampini   }
742628143c3dSStefano Zampini #endif
7427e7931f94SStefano Zampini 
742828143c3dSStefano Zampini   /* assemble new additional is (if any) */
742928143c3dSStefano Zampini   if (nis) {
743028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
743128143c3dSStefano Zampini 
743228143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7433854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
743428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
743528143c3dSStefano Zampini     psum = 0;
743628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
743728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
743828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
743928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
744028143c3dSStefano Zampini         psum += plen;
744128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
744228143c3dSStefano Zampini       }
744328143c3dSStefano Zampini     }
7444854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7445854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
744628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
744728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
744828143c3dSStefano Zampini     }
744928143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
745028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
745128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
745228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
745328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
745428143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
745528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
745628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
745728143c3dSStefano Zampini       }
745828143c3dSStefano Zampini     }
745928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
746028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
746128143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
746228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
746328143c3dSStefano Zampini     }
746428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
746528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
746628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
746728143c3dSStefano Zampini   }
7468e7931f94SStefano Zampini   /* free workspace */
746928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7470e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7471e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7472e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7473e7931f94SStefano Zampini   if (isdense) {
7474e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7475e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
74763b3b1effSJed Brown     ierr = MatISRestoreLocalMat(mat,&local_mat);CHKERRQ(ierr);
7477e7931f94SStefano Zampini   } else {
7478e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7479e7931f94SStefano Zampini   }
748028143c3dSStefano Zampini   if (nis) {
748128143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
748228143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
748328143c3dSStefano Zampini   }
74841ae86dd6SStefano Zampini 
74851ae86dd6SStefano Zampini   if (nvecs) {
74861ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
74871ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
74881ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74891ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
74901ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
74911ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
74921ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
74931ae86dd6SStefano Zampini     /* set values */
74941ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
74951ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
74961ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
74971ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
74981ae86dd6SStefano Zampini       PetscInt j;
74991ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
75001ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
75011ae86dd6SStefano Zampini       }
75021ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
75031ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
75041ae86dd6SStefano Zampini     }
75051ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
75061ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
75071ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
75081ae86dd6SStefano Zampini   }
75091ae86dd6SStefano Zampini 
75101ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
75111ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7512e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7513e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
75141ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
751528143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7516e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7517e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
75181ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
751928143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7520e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7521e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7522e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7523e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7524e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
752528143c3dSStefano Zampini   if (nis) {
752628143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
752728143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
752828143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
752928143c3dSStefano Zampini   }
753028143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
753128143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
753228143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
753328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
753428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
753528143c3dSStefano Zampini     }
75361ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
75371ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
75381ae86dd6SStefano Zampini     }
753953a05cb3SStefano Zampini     *mat_n = NULL;
754028143c3dSStefano Zampini   }
7541e7931f94SStefano Zampini   PetscFunctionReturn(0);
7542e7931f94SStefano Zampini }
7543a57a6d2fSStefano Zampini 
754412edc857SStefano Zampini /* temporary hack into ksp private data structure */
7545af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
754612edc857SStefano Zampini 
7547c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7548c8587f34SStefano Zampini {
7549c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7550c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
755120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
75521ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
75531e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
75549881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
755520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
75566e683305SStefano Zampini   IS                     coarse_is,*isarray;
75576e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
755830368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7559f9eb5b7dSStefano Zampini   PC                     pc_temp;
7560c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7561c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7562f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
75637274672aSStefano Zampini   PetscBool              coarse_reuse;
75641e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
756568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
756622bc73bbSStefano Zampini   PetscScalar            *array;
756757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
756857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
75697de4f681Sstefano_zampini   PetscMPIInt            commsize;
75709881197aSStefano Zampini   PetscErrorCode         ierr;
7571fdc09c96SStefano Zampini 
7572c8587f34SStefano Zampini   PetscFunctionBegin;
7573c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
757468457ee5SStefano 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 */
7575fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
75765a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
75777de4f681Sstefano_zampini 
75787de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
7579fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7580f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7581f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7582f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7583fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
758451bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
758551bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7586727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
7587fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7588fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7589fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7590f4ddd8eeSStefano Zampini       }
7591fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7592fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7593f4ddd8eeSStefano Zampini     }
759470cf5478SStefano Zampini     /* reset any subassembling information */
759557de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
759670cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
759757de7509SStefano Zampini     }
75986e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7599fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7600f4ddd8eeSStefano Zampini   }
760157de7509SStefano Zampini   /* assemble coarse matrix */
760257de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
760357de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
760457de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
760557de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
760618a45a71SStefano Zampini   } else {
760757de7509SStefano Zampini     coarse_mat = NULL;
760857de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
76096e683305SStefano Zampini   }
7610e7931f94SStefano Zampini 
7611abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7612abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7613abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7614abbbba34SStefano Zampini 
7615abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
761622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
761722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
761822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
761922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7620e176bc59SStefano 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);
76216e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
76226e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76236e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7624abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7625abbbba34SStefano Zampini 
762657de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
762757de7509SStefano Zampini   im_active = !!(pcis->n);
762857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
762957de7509SStefano Zampini 
763014f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
763157de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
763257de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
76337de4f681Sstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&commsize);CHKERRQ(ierr);
763457de7509SStefano Zampini   coarse_mat_is = NULL;
763557de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
763657de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
76371ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
763857de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
763957de7509SStefano Zampini   if (multilevel_requested) {
764057de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
764157de7509SStefano Zampini     restr = PETSC_FALSE;
764257de7509SStefano Zampini     full_restr = PETSC_FALSE;
764357de7509SStefano Zampini   } else {
764457de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
764557de7509SStefano Zampini     restr = PETSC_TRUE;
764657de7509SStefano Zampini     full_restr = PETSC_TRUE;
764757de7509SStefano Zampini   }
76487de4f681Sstefano_zampini   if (!pcbddc->coarse_size || commsize == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
764957de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
765057de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7651a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7652bb360cb4SStefano Zampini       if (multilevel_requested) {
7653bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7654bb360cb4SStefano Zampini       } else {
7655bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7656bb360cb4SStefano Zampini       }
7657a198735bSStefano Zampini     } else {
76587de4f681Sstefano_zampini       PetscMPIInt rank;
7659a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
76607de4f681Sstefano_zampini       have_void = (active_procs == (PetscInt)commsize) ? PETSC_FALSE : PETSC_TRUE;
7661a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7662a198735bSStefano Zampini     }
766357de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
766457de7509SStefano Zampini     PetscInt    psum;
766557de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
766657de7509SStefano Zampini     else psum = 0;
766757de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
76687de4f681Sstefano_zampini     if (ncoarse < commsize) have_void = PETSC_TRUE;
766957de7509SStefano Zampini   }
767057de7509SStefano Zampini   /* determine if we can go multilevel */
767157de7509SStefano Zampini   if (multilevel_requested) {
767257de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
767357de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
767457de7509SStefano Zampini   }
767557de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
767657de7509SStefano Zampini 
7677e4d548c7SStefano Zampini   /* dump subassembling pattern */
7678e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7679e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7680e4d548c7SStefano Zampini   }
7681e4d548c7SStefano Zampini 
76826e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
76831e0482f5SStefano Zampini   nedcfield = -1;
76841e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
76856e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
76866e683305SStefano Zampini     const PetscInt         *idxs;
76876e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
76886e683305SStefano Zampini 
76896e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
76900be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
76916e683305SStefano Zampini     /* allocate space for temporary storage */
7692854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7693854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
76946e683305SStefano Zampini     /* allocate for IS array */
76956e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
76961e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
76971e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
76981e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
76991e0482f5SStefano Zampini       } else {
77001e0482f5SStefano Zampini         nedcfield = 0;
77011e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
77021e0482f5SStefano Zampini         nisdofs = 1;
77031e0482f5SStefano Zampini       }
77041e0482f5SStefano Zampini     }
77056e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
770627b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
770730368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7708854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
77096e683305SStefano Zampini     /* dofs splitting */
77106e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
77116e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
77121e0482f5SStefano Zampini       if (nedcfield != i) {
77136e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
77146e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
77156e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
77166e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
77171e0482f5SStefano Zampini       } else {
77181e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
77191e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
77201e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7721eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
77221e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
77231e0482f5SStefano Zampini       }
77246e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
772530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
77266e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
77276e683305SStefano Zampini     }
77286e683305SStefano Zampini     /* neumann boundaries */
77296e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
77306e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
77316e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
77326e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
77336e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
77346e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
77356e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
773630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
77376e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
77386e683305SStefano Zampini     }
77396e683305SStefano Zampini     /* free memory */
77406e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
77416e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
77426e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
77436e683305SStefano Zampini   } else {
77446e683305SStefano Zampini     nis = 0;
77456e683305SStefano Zampini     nisdofs = 0;
77466e683305SStefano Zampini     nisneu = 0;
774730368db7SStefano Zampini     nisvert = 0;
77486e683305SStefano Zampini     isarray = NULL;
77496e683305SStefano Zampini   }
77506e683305SStefano Zampini   /* destroy no longer needed map */
77516e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
77526e683305SStefano Zampini 
775357de7509SStefano Zampini   /* subassemble */
775457de7509SStefano Zampini   if (multilevel_allowed) {
77551ae86dd6SStefano Zampini     Vec       vp[1];
77561ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
775757de7509SStefano Zampini     PetscBool reuse,reuser;
77581ae86dd6SStefano Zampini 
775957de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
776057de7509SStefano Zampini     else reuse = PETSC_FALSE;
776157de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
77621ae86dd6SStefano Zampini     vp[0] = NULL;
77631ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
77641ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
77651ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
77661ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
77671ae86dd6SStefano Zampini       nvecs = 1;
77681ae86dd6SStefano Zampini 
77691ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7770a198735bSStefano Zampini         Mat      B,loc_divudotp;
77711ae86dd6SStefano Zampini         Vec      v,p;
77721ae86dd6SStefano Zampini         IS       dummy;
77731ae86dd6SStefano Zampini         PetscInt np;
77741ae86dd6SStefano Zampini 
7775a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7776a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
77771ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
77787dae84e0SHong Zhang         ierr = MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
77791ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
77801ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
77811ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
77821ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
77831ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
77841ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
77851ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
77861ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
77871ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
77881ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
77891ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
77901ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
779174e2c79eSStefano Zampini       }
77921ae86dd6SStefano Zampini     }
77931ae86dd6SStefano Zampini     if (reuser) {
77941e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
779574e2c79eSStefano Zampini     } else {
77961e0482f5SStefano 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);
77971ae86dd6SStefano Zampini     }
77981ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
77991ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
78001ae86dd6SStefano Zampini       PetscInt    nl;
78011ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
78021ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
78031ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
78041ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
78051ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
78061ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
78071ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
78081ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7809a198735bSStefano Zampini     } else {
7810a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
78111ae86dd6SStefano Zampini     }
78121ae86dd6SStefano Zampini   } else {
78131e0482f5SStefano 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);
78146e683305SStefano Zampini   }
781557de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
781657de7509SStefano Zampini     PetscMPIInt size;
7817f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
781857de7509SStefano Zampini     if (!multilevel_allowed) {
781957de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
78206e683305SStefano Zampini     } else {
782157de7509SStefano Zampini       Mat A;
7822779c1cceSStefano Zampini 
782357de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
782457de7509SStefano Zampini       if (coarse_mat_is) {
782557de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
782657de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
782757de7509SStefano Zampini         coarse_mat = coarse_mat_is;
782857de7509SStefano Zampini       }
782957de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
783057de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
783157de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7832779c1cceSStefano Zampini     }
7833779c1cceSStefano Zampini   }
783457de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
783557de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
78366e683305SStefano Zampini 
78376e683305SStefano Zampini   /* create local to global scatters for coarse problem */
783868457ee5SStefano Zampini   if (compute_vecs) {
78396e683305SStefano Zampini     PetscInt lrows;
78406e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
784157de7509SStefano Zampini     if (coarse_mat) {
784257de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
78436e683305SStefano Zampini     } else {
78446e683305SStefano Zampini       lrows = 0;
78456e683305SStefano Zampini     }
78466e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
78476e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
78486e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
78496e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
78506e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
78516e683305SStefano Zampini   }
78526e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7853c8587f34SStefano Zampini 
7854f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7855f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7856f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7857f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7858f9eb5b7dSStefano Zampini   } else {
7859f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7860f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7861c8587f34SStefano Zampini   }
7862c8587f34SStefano Zampini 
78636e683305SStefano Zampini   /* print some info if requested */
78646e683305SStefano Zampini   if (pcbddc->dbg_flag) {
78656e683305SStefano Zampini     if (!multilevel_allowed) {
78666e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
78676e683305SStefano Zampini       if (multilevel_requested) {
78686e683305SStefano 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);
78696e683305SStefano Zampini       } else if (pcbddc->max_levels) {
78706e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
78716e683305SStefano Zampini       }
78726e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
78736e683305SStefano Zampini     }
78746e683305SStefano Zampini   }
78756e683305SStefano Zampini 
78761e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
78771e0482f5SStefano Zampini   coarseG = NULL;
78781e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
78791e0482f5SStefano Zampini     MPI_Comm ccomm;
78801e0482f5SStefano Zampini     if (coarse_mat) {
78811e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
78821e0482f5SStefano Zampini     } else {
78831e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
78841e0482f5SStefano Zampini     }
78851e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
78861e0482f5SStefano Zampini   }
78871e0482f5SStefano Zampini 
7888f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
788957de7509SStefano Zampini   if (coarse_mat) {
78907274672aSStefano Zampini     PetscBool   isredundant,isnn,isbddc;
78916a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
78927274672aSStefano Zampini 
78936e683305SStefano Zampini     if (pcbddc->dbg_flag) {
789457de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
78956e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
78966e683305SStefano Zampini     }
7897f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7898312be037SStefano Zampini       char prefix[256],str_level[16];
7899e604994aSStefano Zampini       size_t len;
79001e0482f5SStefano Zampini 
790157de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7902422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7903c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7904f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
790557de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7906c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
79076e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7908c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
79091e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
7910c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7911e604994aSStefano Zampini       /* prefix */
7912e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7913e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7914e604994aSStefano Zampini       if (!pcbddc->current_level) {
7915e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7916e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7917c8587f34SStefano Zampini       } else {
7918e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7919312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7920312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
792134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
792235529e7bSStefano Zampini         ierr = PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level));CHKERRQ(ierr);
7923e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7924e604994aSStefano Zampini       }
7925e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
79263e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
79273e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
79283e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
79293e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7930f9eb5b7dSStefano Zampini       /* allow user customization */
7931f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
79323e3c6dadSStefano Zampini     }
79333e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
793451bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
79353e3c6dadSStefano Zampini     if (nisdofs) {
79363e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
79373e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
79383e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
79393e3c6dadSStefano Zampini       }
79403e3c6dadSStefano Zampini     }
79413e3c6dadSStefano Zampini     if (nisneu) {
79423e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
79433e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7944312be037SStefano Zampini     }
794530368db7SStefano Zampini     if (nisvert) {
794630368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
794730368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
794830368db7SStefano Zampini     }
79491e0482f5SStefano Zampini     if (coarseG) {
79501e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
79511e0482f5SStefano Zampini     }
7952f9eb5b7dSStefano Zampini 
7953f9eb5b7dSStefano Zampini     /* get some info after set from options */
7954f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
7955b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
7956b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
7957f9eb5b7dSStefano Zampini       ierr   = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7958f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7959f9eb5b7dSStefano Zampini     }
7960b76f3995Sstefano_zampini     /* multilevel cannot be done with coarse PCs different from BDDC or NN */
79617274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
79627274672aSStefano Zampini     if (multilevel_requested && multilevel_allowed && !isbddc && !isnn) {
7963b76f3995Sstefano_zampini       ierr   = PCSetType(pc_temp,PCBDDC);CHKERRQ(ierr);
7964b76f3995Sstefano_zampini       isbddc = PETSC_TRUE;
7965b76f3995Sstefano_zampini     }
79667274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
79674f3a063dSStefano Zampini     if (isredundant) {
79684f3a063dSStefano Zampini       KSP inner_ksp;
79694f3a063dSStefano Zampini       PC  inner_pc;
79709326c5c6Sstefano_zampini 
79714f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
79724f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
79734f3a063dSStefano Zampini     }
7974f9eb5b7dSStefano Zampini 
797557de7509SStefano Zampini     /* parameters which miss an API */
79767274672aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
797757de7509SStefano Zampini     if (isbddc) {
7978720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
79797274672aSStefano Zampini 
7980720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
798157de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
798227b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
798327b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7984a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7985a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7986a198735bSStefano Zampini         IS                     row,col;
7987a198735bSStefano Zampini         const PetscInt         *gidxs;
7988a198735bSStefano Zampini         PetscInt               n,st,M,N;
7989a198735bSStefano Zampini 
7990a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7991a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7992a198735bSStefano Zampini         st   = st-n;
7993a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7994a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7995a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7996a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7997a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7998a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7999a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
8000a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
8001a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
8002a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
8003a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
8004a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
8005a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
8006a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
8007a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
8008a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
8009a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
8010a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
8011a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
8012a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
80138ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
8014a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
8015720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
801659e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8017720d30f9SStefano Zampini       }
8018d4d8cf7bSStefano Zampini     }
80199881197aSStefano Zampini 
80203301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
80215a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
80223301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
80233301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
80243301b35fSStefano Zampini     }
80253301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
80263301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
80273301b35fSStefano Zampini     }
80283301b35fSStefano Zampini     if (pc->pmat->spd_set) {
80293301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
80303301b35fSStefano Zampini     }
803127b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
803227b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
803327b6a85dSStefano Zampini     }
80346e683305SStefano Zampini     /* set operators */
80355f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
80366e683305SStefano Zampini     if (pcbddc->dbg_flag) {
80376e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
80386e683305SStefano Zampini     }
80396e683305SStefano Zampini   }
80401e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
80416e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
8042b1ecc7b1SStefano Zampini #if 0
8043b9b85e73SStefano Zampini   {
8044b9b85e73SStefano Zampini     PetscViewer viewer;
8045b9b85e73SStefano Zampini     char filename[256];
8046b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
8047b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
80486a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
8049b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
8050f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
8051b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
8052b9b85e73SStefano Zampini   }
8053b9b85e73SStefano Zampini #endif
8054f9eb5b7dSStefano Zampini 
805598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
805698a51de6SStefano Zampini     Vec crhs,csol;
805704708bb6SStefano Zampini 
8058f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
8059f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
8060f347579bSStefano Zampini     if (!csol) {
80612a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
8062f9eb5b7dSStefano Zampini     }
8063f347579bSStefano Zampini     if (!crhs) {
80642a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
8065f347579bSStefano Zampini     }
8066b0f5fe93SStefano Zampini   }
80671ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
8068b0f5fe93SStefano Zampini 
8069b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8070b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8071b0f5fe93SStefano Zampini 
8072b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
80734f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
80744f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
80754f1b2e48SStefano Zampini     }
8076b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
8077b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
8078b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8079b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8080b0f5fe93SStefano Zampini     if (coarse_mat) {
8081b0f5fe93SStefano Zampini       Vec         nullv;
8082b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8083b0f5fe93SStefano Zampini       PetscInt    nl;
8084b0f5fe93SStefano Zampini 
8085b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
8086b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
8087b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8088b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
8089b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
8090b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
8091b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
8092b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
8093b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
8094b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
8095b0f5fe93SStefano Zampini     }
8096b0f5fe93SStefano Zampini   }
8097b0f5fe93SStefano Zampini 
8098b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8099b0f5fe93SStefano Zampini     PetscBool ispreonly;
8100b0f5fe93SStefano Zampini 
8101b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8102b0f5fe93SStefano Zampini       PetscBool isnull;
8103b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
8104bef83e63SStefano Zampini       if (isnull) {
8105b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
8106b0f5fe93SStefano Zampini       }
8107bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8108b0f5fe93SStefano Zampini     }
8109b0f5fe93SStefano Zampini     /* setup coarse ksp */
8110b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
8111cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
8112cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
81136e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
8114c8587f34SStefano Zampini       KSP       check_ksp;
81152b510759SStefano Zampini       KSPType   check_ksp_type;
8116c8587f34SStefano Zampini       PC        check_pc;
81176e683305SStefano Zampini       Vec       check_vec,coarse_vec;
81186a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
81192b510759SStefano Zampini       PetscInt  its;
81206e683305SStefano Zampini       PetscBool compute_eigs;
81216e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
81226e683305SStefano Zampini       PetscInt  neigs;
81238e185a42SStefano Zampini       const char *prefix;
8124c8587f34SStefano Zampini 
81252b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
81266e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
8127422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
812823ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
8129f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
8130e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
8131e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
8132e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
81332b510759SStefano Zampini       if (ispreonly) {
81342b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
81356e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
81362b510759SStefano Zampini       } else {
8137cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
81386e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8139c8587f34SStefano Zampini       }
8140c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
81416e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
81426e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
81436e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
8144a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
8145a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
8146a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
8147a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
8148c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
8149c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
8150c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
8151c8587f34SStefano Zampini       /* create random vec */
81522701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
8153c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
81546e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
8155c8587f34SStefano Zampini       /* solve coarse problem */
81566e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
8157cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
81586e683305SStefano Zampini       if (compute_eigs) {
8159854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
8160854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
81616e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
81621ae86dd6SStefano Zampini         if (neigs) {
81636e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
81646e683305SStefano Zampini           lambda_min = eigs_r[0];
81656e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
81662701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
81672701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
8168cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
8169cbcc2c2aSStefano Zampini             }
8170c8587f34SStefano Zampini           }
8171c8587f34SStefano Zampini         }
81721ae86dd6SStefano Zampini       }
8173cbcc2c2aSStefano Zampini 
8174c8587f34SStefano Zampini       /* check coarse problem residual error */
81756e683305SStefano Zampini       if (pcbddc->dbg_flag) {
81766e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
81776e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
81786e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
8179c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
81806e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
81816e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
8182779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
81836e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
81846e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
81856e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
81866e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
8187b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
8188b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
8189b0f5fe93SStefano Zampini         }
81906e683305SStefano Zampini         if (compute_eigs) {
81916e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8192b03ebc13SStefano Zampini           KSPConvergedReason reason;
8193deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
8194c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
8195b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
81966e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
8197b03ebc13SStefano 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);
81986e683305SStefano Zampini           for (i=0;i<neigs;i++) {
81996e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
8200c8587f34SStefano Zampini           }
82016e683305SStefano Zampini         }
82026e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
82036e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
82046e683305SStefano Zampini       }
8205e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
82062701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
8207c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
82086e683305SStefano Zampini       if (compute_eigs) {
82096e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
82106e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
8211c8587f34SStefano Zampini       }
82126e683305SStefano Zampini     }
82136e683305SStefano Zampini   }
8214bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
8215cbcc2c2aSStefano Zampini   /* print additional info */
8216cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
82176e683305SStefano Zampini     /* waits until all processes reaches this point */
82186e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
8219cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
8220cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8221cbcc2c2aSStefano Zampini   }
8222cbcc2c2aSStefano Zampini 
82232b510759SStefano Zampini   /* free memory */
8224fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
8225c8587f34SStefano Zampini   PetscFunctionReturn(0);
8226c8587f34SStefano Zampini }
8227674ae819SStefano Zampini 
8228f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8229f34684f1SStefano Zampini {
8230f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8231f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8232f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8233dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8234dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
823573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8236dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8237f34684f1SStefano Zampini   PetscErrorCode ierr;
8238f34684f1SStefano Zampini 
8239f34684f1SStefano Zampini   PetscFunctionBegin;
8240f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
82416c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
8242dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
82433bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
8244dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8245dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
82466583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
8247dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
8248dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
8249dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
82506c4ed002SBarry 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);
8251dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
8252dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8253dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
8254dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
8255dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
8256f34684f1SStefano Zampini 
8257f34684f1SStefano Zampini   /* check numbering */
8258f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8259019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8260dc456d91SStefano Zampini     PetscInt    i;
8261b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8262f34684f1SStefano Zampini 
8263f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8264f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8265f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
82661575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8267019a44ceSStefano Zampini     /* counter */
8268019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8269019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
8270019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8271019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8272019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8273019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8274f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
8275f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
8276727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
8277f34684f1SStefano Zampini     }
8278f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8279f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8280f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8281e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8282e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8283e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8284e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8285f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8286019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8287f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8288019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
82892c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
829075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8291b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
82922c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
82932c66d082SStefano 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);
8294f34684f1SStefano Zampini       }
8295f34684f1SStefano Zampini     }
8296019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
8297b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
8298f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8299f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8300f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8301f34684f1SStefano Zampini     }
8302f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8303f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
8304e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8305e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8306f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
8307f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
8308b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8309ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8310ca8b9ea9SStefano Zampini 
8311ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
83123bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
8313f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
8314f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8315f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
8316f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
83174bc2dc4bSStefano 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);
8318f34684f1SStefano Zampini       }
8319f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8320ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
8321f34684f1SStefano Zampini     }
8322f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
83231575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8324302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8325f34684f1SStefano Zampini   }
83268bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
8327f34684f1SStefano Zampini   /* get back data */
8328f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8329f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8330674ae819SStefano Zampini   PetscFunctionReturn(0);
8331674ae819SStefano Zampini }
8332674ae819SStefano Zampini 
8333a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8334e456f2a8SStefano Zampini {
8335e456f2a8SStefano Zampini   IS             localis_t;
8336a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8337e456f2a8SStefano Zampini   PetscScalar    *vals;
8338e456f2a8SStefano Zampini   PetscErrorCode ierr;
8339e456f2a8SStefano Zampini 
8340e456f2a8SStefano Zampini   PetscFunctionBegin;
8341a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
8342e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
8343854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
8344e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8345e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8346a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8347a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
83481035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
83493151afb1SStefano Zampini     ierr = VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr);
8350a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
83511035eff8SStefano Zampini   }
8352a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8353e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8354e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8355a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8356a7dc3881SStefano Zampini   /* now compute set in local ordering */
8357a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8358a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8359a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8360a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8361a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8362ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8363e456f2a8SStefano Zampini       lsize++;
8364e456f2a8SStefano Zampini     }
8365e456f2a8SStefano Zampini   }
8366854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8367a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8368ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8369e456f2a8SStefano Zampini       idxs[lsize++] = i;
8370e456f2a8SStefano Zampini     }
8371e456f2a8SStefano Zampini   }
8372a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8373a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8374e456f2a8SStefano Zampini   *localis = localis_t;
8375e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8376e456f2a8SStefano Zampini }
8377906d46d4SStefano Zampini 
837808122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8379b96c3477SStefano Zampini {
8380a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8381b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8382b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8383a64f4aa4SStefano Zampini   Mat                 S_j;
8384b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8385b96c3477SStefano Zampini   PetscBool           free_used_adj;
8386b96c3477SStefano Zampini   PetscErrorCode      ierr;
8387b96c3477SStefano Zampini 
8388b96c3477SStefano Zampini   PetscFunctionBegin;
8389b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8390b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
839108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8392b96c3477SStefano Zampini     used_xadj = NULL;
8393b96c3477SStefano Zampini     used_adjncy = NULL;
8394b96c3477SStefano Zampini   } else {
839508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
839608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
839708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
839808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8399b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8400b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8401b96c3477SStefano Zampini     } else {
84022fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8403b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8404b96c3477SStefano Zampini       PetscInt       nvtxs;
8405b96c3477SStefano Zampini 
84062fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
84072fffb893SStefano Zampini       if (flg_row) {
8408b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8409b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8410b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8411b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
84122fffb893SStefano Zampini       } else {
84132fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
84142fffb893SStefano Zampini         used_xadj = NULL;
84152fffb893SStefano Zampini         used_adjncy = NULL;
84162fffb893SStefano Zampini       }
84172fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8418b96c3477SStefano Zampini     }
8419b96c3477SStefano Zampini   }
8420d5574798SStefano Zampini 
8421d5574798SStefano Zampini   /* setup sub_schurs data */
8422a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8423df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8424df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8425a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
842691af6908SStefano 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);
8427a64f4aa4SStefano Zampini   } else {
842872b8c272SStefano Zampini     Mat       change = NULL;
84299d54b7f4SStefano Zampini     Vec       scaling = NULL;
8430111315fdSstefano_zampini     IS        change_primal = NULL, iP;
8431111315fdSstefano_zampini     PetscInt  benign_n;
8432111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
8433111315fdSstefano_zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8434111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
8435a3df083aSStefano Zampini 
84365feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
84375feab87aSStefano Zampini       PetscInt n_vertices;
84385feab87aSStefano Zampini 
84395feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
84402034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
84415feab87aSStefano Zampini     }
844204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
844304708bb6SStefano Zampini     if (!isseqaij) {
844404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
844504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
844604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
844704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
844804708bb6SStefano Zampini       } else {
8449511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
845004708bb6SStefano Zampini       }
845104708bb6SStefano Zampini     }
8452a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8453a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8454ca92afb2SStefano Zampini     } else {
8455a3df083aSStefano Zampini       benign_n = 0;
8456ca92afb2SStefano Zampini     }
8457b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8458b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8459b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
846072b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
846122db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8462b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
846322db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8464b7ab4a40SStefano Zampini     }
8465b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8466b7ab4a40SStefano 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 */
8467b7ab4a40SStefano Zampini     if (need_change) {
846888c03ad3SStefano Zampini       PC_IS   *pcisf;
846988c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
847088c03ad3SStefano Zampini       PC      pcf;
847188c03ad3SStefano Zampini 
8472e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
847388c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
847488c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
847588c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
8476b9be95fcSstefano_zampini 
847788c03ad3SStefano Zampini       /* hacks */
847888c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
847972b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
848072b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
848172b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
848272b8c272SStefano Zampini       pcisf->n                     = pcis->n;
848372b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
848488c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
848588c03ad3SStefano Zampini       ierr                         = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
848688c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
848788c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
848888c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
848988c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
849072b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
849188c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
8492b9be95fcSstefano_zampini 
8493b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
849488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
849572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
849672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
849772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
849872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
8499b9be95fcSstefano_zampini 
850088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
850172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
850288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
850388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
850488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
850588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
850688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
850788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
8508b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
850988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
851088c03ad3SStefano Zampini     }
85119d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
8512111315fdSstefano_zampini 
8513111315fdSstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP);CHKERRQ(ierr);
8514111315fdSstefano_zampini     if (iP) {
8515111315fdSstefano_zampini       ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr);
8516111315fdSstefano_zampini       ierr = PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL);CHKERRQ(ierr);
8517111315fdSstefano_zampini       ierr = PetscOptionsEnd();CHKERRQ(ierr);
8518111315fdSstefano_zampini     }
8519111315fdSstefano_zampini     if (discrete_harmonic) {
8520111315fdSstefano_zampini       Mat A;
8521111315fdSstefano_zampini       ierr = MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
8522111315fdSstefano_zampini       ierr = MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL);CHKERRQ(ierr);
8523111315fdSstefano_zampini       ierr = PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP);CHKERRQ(ierr);
8524111315fdSstefano_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);
8525111315fdSstefano_zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
8526111315fdSstefano_zampini     } else {
852791af6908SStefano 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);
8528111315fdSstefano_zampini     }
852972b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
853072b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8531ca92afb2SStefano Zampini   }
8532d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8533b96c3477SStefano Zampini 
8534b96c3477SStefano Zampini   /* free adjacency */
8535b96c3477SStefano Zampini   if (free_used_adj) {
8536b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8537b96c3477SStefano Zampini   }
8538b96c3477SStefano Zampini   PetscFunctionReturn(0);
8539b96c3477SStefano Zampini }
8540b96c3477SStefano Zampini 
854108122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8542b96c3477SStefano Zampini {
8543b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8544b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8545b96c3477SStefano Zampini   PCBDDCGraph         graph;
8546b96c3477SStefano Zampini   PetscErrorCode      ierr;
8547b96c3477SStefano Zampini 
8548b96c3477SStefano Zampini   PetscFunctionBegin;
8549b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
855008122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
85513301b35fSStefano Zampini     IS       verticesIS,verticescomm;
85523301b35fSStefano Zampini     PetscInt vsize,*idxs;
8553b96c3477SStefano Zampini 
8554b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
85553301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
85563301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
85573301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
85583301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8559c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8560b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8561be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8562441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
85633301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8564b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8565b96c3477SStefano Zampini   } else {
8566b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8567b96c3477SStefano Zampini   }
8568e4d548c7SStefano Zampini   /* print some info */
85695c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8570e4d548c7SStefano Zampini     IS       vertices;
8571e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8572c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8573e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8574e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8575e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8576e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8577e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8578e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8579e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8580e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8581e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8582c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8583e4d548c7SStefano Zampini   }
8584b96c3477SStefano Zampini 
8585b96c3477SStefano Zampini   /* sub_schurs init */
8586b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8587b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8588b334f244SStefano Zampini   }
85898b6046baSStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
8590e62b6521Sstefano_zampini   pcbddc->sub_schurs->prefix = ((PetscObject)pc)->prefix;
8591a64f4aa4SStefano Zampini 
8592b96c3477SStefano Zampini   /* free graph struct */
859308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8594b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8595b96c3477SStefano Zampini   }
8596b96c3477SStefano Zampini   PetscFunctionReturn(0);
8597b96c3477SStefano Zampini }
8598fa34dd3eSStefano Zampini 
8599fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8600fa34dd3eSStefano Zampini {
8601fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8602fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8603fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8604fa34dd3eSStefano Zampini 
8605fa34dd3eSStefano Zampini   PetscFunctionBegin;
8606fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8607fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
86084f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8609fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
86104f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
861175c01103SStefano Zampini     PetscReal      norm;
8612fa34dd3eSStefano Zampini     PetscInt       i;
8613fa34dd3eSStefano Zampini 
8614fa34dd3eSStefano Zampini     /* B0 and B0_B */
8615fa34dd3eSStefano Zampini     if (zerodiag) {
8616fa34dd3eSStefano Zampini       IS       dummy;
8617fa34dd3eSStefano Zampini 
86184f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
86197dae84e0SHong Zhang       ierr = MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8620fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8621fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8622fa34dd3eSStefano Zampini     }
8623fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8624fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8625fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8626fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8627fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8628fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8629fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8630fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8631fa34dd3eSStefano Zampini     /* S_j */
8632fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8633fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8634fa34dd3eSStefano Zampini 
8635fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8636fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8637fa34dd3eSStefano Zampini     /* continuous in primal space */
8638fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8639fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8640fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8641fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
86424f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
86434f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8644fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8645fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8646fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8647fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8648fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8649fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8650fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8651fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8652fa34dd3eSStefano Zampini 
8653fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8654fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8655fa34dd3eSStefano Zampini     /* local with Schur */
8656fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8657fa34dd3eSStefano Zampini     if (zerodiag) {
8658fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
86594f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8660fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8661fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8662fa34dd3eSStefano Zampini     }
8663fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8664fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8665fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8666fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8667fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8668fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8669fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8670fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8671fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8672fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8673fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8674fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8675fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8676fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8677fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8678fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8679fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8680fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8681fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8682fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8683fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8684fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8685fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8686fa34dd3eSStefano Zampini     if (zerodiag) {
8687fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8688fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
86894f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8690fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8691fa34dd3eSStefano Zampini     }
8692fa34dd3eSStefano Zampini     /* BDDC */
8693fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8694fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8695fa34dd3eSStefano Zampini 
8696fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8697fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8698fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8699fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
87004f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
87014f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8702fa34dd3eSStefano Zampini     }
87034f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8704fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8705fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8706fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8707fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8708fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8709fa34dd3eSStefano Zampini   }
8710fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8711fa34dd3eSStefano Zampini }
87121e0482f5SStefano Zampini 
87131e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
87141e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
87151e0482f5SStefano Zampini {
87161e0482f5SStefano Zampini   Mat            At;
87171e0482f5SStefano Zampini   IS             rows;
87181e0482f5SStefano Zampini   PetscInt       rst,ren;
87191e0482f5SStefano Zampini   PetscErrorCode ierr;
87201e0482f5SStefano Zampini   PetscLayout    rmap;
87211e0482f5SStefano Zampini 
87221e0482f5SStefano Zampini   PetscFunctionBegin;
87231e0482f5SStefano Zampini   rst = ren = 0;
87241e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
87251e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
87261e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
87271e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
87281e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
87291e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
87301e0482f5SStefano Zampini   }
8731e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
87327dae84e0SHong Zhang   ierr = MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
87331e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
87341e0482f5SStefano Zampini 
87351e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
87361e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
87371e0482f5SStefano Zampini     IS         from,to;
87381e0482f5SStefano Zampini     Vec        gvec;
87391e0482f5SStefano Zampini     PetscInt   lsize;
87401e0482f5SStefano Zampini 
87411e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
87421e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
87431e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
87441e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
87451e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
87461e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
87471e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
87481e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
87491e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
87501e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
87511e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
87521e0482f5SStefano Zampini     b->A = a->A;
87531e0482f5SStefano Zampini     b->B = a->B;
87541e0482f5SStefano Zampini 
87551e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
87561e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
87571e0482f5SStefano Zampini     b->rowindices      = 0;
87581e0482f5SStefano Zampini     b->rowvalues       = 0;
87591e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
87601e0482f5SStefano Zampini 
87611e0482f5SStefano Zampini     (*B)->rmap         = rmap;
87621e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
87631e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
87641e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
87651e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
87661e0482f5SStefano Zampini 
87671e0482f5SStefano Zampini     if (a->colmap) {
87681e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
87691e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
87701e0482f5SStefano Zampini #else
87711e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
87721e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
87731e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
87741e0482f5SStefano Zampini #endif
87751e0482f5SStefano Zampini     } else b->colmap = 0;
87761e0482f5SStefano Zampini     if (a->garray) {
87771e0482f5SStefano Zampini       PetscInt len;
87781e0482f5SStefano Zampini       len  = a->B->cmap->n;
87791e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
87801e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
87811e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
87821e0482f5SStefano Zampini     } else b->garray = 0;
87831e0482f5SStefano Zampini 
87841e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
87851e0482f5SStefano Zampini     b->lvec = a->lvec;
87861e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
87871e0482f5SStefano Zampini 
87881e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
87891e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
87901e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
87911e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
87921e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
87931e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
87941e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
87951e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
87961e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
87971e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
87981e0482f5SStefano Zampini   }
87991e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
88001e0482f5SStefano Zampini   PetscFunctionReturn(0);
88011e0482f5SStefano Zampini }
8802